diff --git a/devices/8139too-2.6.13-ethercat.c b/devices/8139too-2.6.13-ethercat.c deleted file mode 100644 index a939d565..00000000 --- a/devices/8139too-2.6.13-ethercat.c +++ /dev/null @@ -1,2783 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.27" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -const static struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int default_port:4; /* Last dev->if_port value. */ - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - pid_t thr_pid; - wait_queue_head_t thr_wait; - struct completion thr_exited; - u32 rx_config; - struct rtl_extra_stats xstats; - int time_to_die; - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct net_device *dev); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pci_name(pdev)); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - printk (KERN_ERR PFX "%s: region #0 not a PIO resource, aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI I/O region size(s), aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - printk (KERN_ERR PFX "%s: region #1 not an MMIO resource, aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI mem region size(s), aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, "8139too"); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev)); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev)); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - printk (KERN_ERR PFX "%s: Chip not responding, ignoring board\n", - pci_name(pdev)); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - printk (KERN_DEBUG PFX "%s: unknown chip version, assuming RTL-8139\n", - pci_name(pdev)); - printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pci_name(pdev), RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - printk(KERN_INFO PFX "pci dev %s (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pci_name(pdev), pdev->vendor, pdev->device, pci_rev); - printk(KERN_INFO PFX "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - init_waitqueue_head (&tp->thr_wait); - init_completion (&tp->thr_exited); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - SA_SHIRQ, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#lx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", - dev->name, pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(dev); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static int rtl8139_thread (void *data) -{ - struct net_device *dev = data; - struct rtl8139_private *tp = netdev_priv(dev); - unsigned long timeout; - - daemonize("%s", dev->name); - allow_signal(SIGTERM); - - while (1) { - timeout = next_tick; - do { - timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout); - /* make swsusp happy with our thread */ - try_to_freeze(); - } while (!signal_pending (current) && (timeout > 0)); - - if (signal_pending (current)) { - flush_signals(current); - } - - if (tp->time_to_die) - break; - - if (rtnl_lock_interruptible ()) - break; - rtl8139_thread_iter (dev, tp, tp->mmio_addr); - rtnl_unlock (); - } - - complete_and_exit (&tp->thr_exited, 0); -} - -static void rtl8139_start_thread(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->thr_pid = -1; - tp->twistie = 0; - tp->time_to_die = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->thr_pid = kernel_thread(rtl8139_thread, dev, CLONE_FS|CLONE_FILES); - if (tp->thr_pid < 0) { - printk (KERN_WARNING "%s: unable to start kernel thread\n", - dev->name); - } -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - unsigned long flags; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irqsave (&tp->lock, flags); - rtl8139_tx_clear (tp); - spin_unlock_irqrestore (&tp->lock, flags); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock(&tp->rx_lock); - } -} - - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - if (!tp->ecdev) spin_lock_irq(&tp->lock); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if (!tp->ecdev) { - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irq(&tp->lock); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - memcpy(skb->data, ring + offset, left); - memcpy(skb->data+left, ring, size - left); - } else - memcpy(skb->data, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, - &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_disable(); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_enable(); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev, NULL); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } - else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev, NULL); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue (dev); - - if (tp->thr_pid >= 0) { - tp->time_to_die = 1; - wmb(); - ret = kill_proc (tp->thr_pid, SIGTERM, 1); - if (ret) { - printk (KERN_ERR "%s: unable to signal thread\n", dev->name); - return ret; - } - wait_for_completion (&tp->thr_exited); - } - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_module_init (&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.13-orig.c b/devices/8139too-2.6.13-orig.c deleted file mode 100644 index 4c2cf7bb..00000000 --- a/devices/8139too-2.6.13-orig.c +++ /dev/null @@ -1,2646 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.27" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -const static struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int default_port:4; /* Last dev->if_port value. */ - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - pid_t thr_pid; - wait_queue_head_t thr_wait; - struct completion thr_exited; - u32 rx_config; - struct rtl_extra_stats xstats; - int time_to_die; - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct net_device *dev); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pci_name(pdev)); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - printk (KERN_ERR PFX "%s: region #0 not a PIO resource, aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI I/O region size(s), aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - printk (KERN_ERR PFX "%s: region #1 not an MMIO resource, aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI mem region size(s), aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, "8139too"); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev)); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev)); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - printk (KERN_ERR PFX "%s: Chip not responding, ignoring board\n", - pci_name(pdev)); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - printk (KERN_DEBUG PFX "%s: unknown chip version, assuming RTL-8139\n", - pci_name(pdev)); - printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pci_name(pdev), RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - printk(KERN_INFO PFX "pci dev %s (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pci_name(pdev), pdev->vendor, pdev->device, pci_rev); - printk(KERN_INFO PFX "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - init_waitqueue_head (&tp->thr_wait); - init_completion (&tp->thr_exited); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#lx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", - dev->name, pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(dev); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static int rtl8139_thread (void *data) -{ - struct net_device *dev = data; - struct rtl8139_private *tp = netdev_priv(dev); - unsigned long timeout; - - daemonize("%s", dev->name); - allow_signal(SIGTERM); - - while (1) { - timeout = next_tick; - do { - timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout); - /* make swsusp happy with our thread */ - try_to_freeze(); - } while (!signal_pending (current) && (timeout > 0)); - - if (signal_pending (current)) { - flush_signals(current); - } - - if (tp->time_to_die) - break; - - if (rtnl_lock_interruptible ()) - break; - rtl8139_thread_iter (dev, tp, tp->mmio_addr); - rtnl_unlock (); - } - - complete_and_exit (&tp->thr_exited, 0); -} - -static void rtl8139_start_thread(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->thr_pid = -1; - tp->twistie = 0; - tp->time_to_die = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->thr_pid = kernel_thread(rtl8139_thread, dev, CLONE_FS|CLONE_FILES); - if (tp->thr_pid < 0) { - printk (KERN_WARNING "%s: unable to start kernel thread\n", - dev->name); - } -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - unsigned long flags; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irqsave (&tp->lock, flags); - rtl8139_tx_clear (tp); - spin_unlock_irqrestore (&tp->lock, flags); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock(&tp->rx_lock); -} - - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - spin_lock_irq(&tp->lock); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irq(&tp->lock); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - memcpy(skb->data, ring + offset, left); - memcpy(skb->data+left, ring, size - left); - } else - memcpy(skb->data, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_disable(); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_enable(); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev, NULL); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - unsigned long flags; - - netif_stop_queue (dev); - - if (tp->thr_pid >= 0) { - tp->time_to_die = 1; - wmb(); - ret = kill_proc (tp->thr_pid, SIGTERM, 1); - if (ret) { - printk (KERN_ERR "%s: unable to signal thread\n", dev->name); - return ret; - } - wait_for_completion (&tp->thr_exited); - } - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_module_init (&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.17-ethercat.c b/devices/8139too-2.6.17-ethercat.c deleted file mode 100644 index d41ef213..00000000 --- a/devices/8139too-2.6.17-ethercat.c +++ /dev/null @@ -1,2778 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.27" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct work_struct thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (void *_data); -static void rtl8139_tx_timeout_task(void *_data); -static struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pci_name(pdev)); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - printk (KERN_ERR PFX "%s: region #0 not a PIO resource, aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI I/O region size(s), aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - printk (KERN_ERR PFX "%s: region #1 not an MMIO resource, aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI mem region size(s), aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, "8139too"); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev)); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev)); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - printk (KERN_ERR PFX "%s: Chip not responding, ignoring board\n", - pci_name(pdev)); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - printk (KERN_DEBUG PFX "%s: unknown chip version, assuming RTL-8139\n", - pci_name(pdev)); - printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pci_name(pdev), RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - printk(KERN_INFO PFX "pci dev %s (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pci_name(pdev), pdev->vendor, pdev->device, pci_rev); - printk(KERN_INFO PFX "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_WORK(&tp->thread, rtl8139_thread, dev); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - SA_SHIRQ, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#lx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", - dev->name, pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - unsigned long thr_delay = next_tick; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(_data); - } else if (rtnl_trylock()) { - rtl8139_thread_iter (dev, tp, tp->mmio_addr); - rtnl_unlock (); - } else { - /* unlikely race. mitigate with fast poll. */ - thr_delay = HZ / 2; - } - - schedule_delayed_work(&tp->thread, thr_delay); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static void rtl8139_stop_thread(struct rtl8139_private *tp) -{ - if (tp->have_thread) { - cancel_rearming_delayed_work(&tp->thread); - tp->have_thread = 0; - } else - flush_scheduled_work(); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (!tp->ecdev && !tp->have_thread) { - INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); - schedule_delayed_work(&tp->thread, next_tick); - } else - tp->watchdog_fired = 1; - -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - if (!tp->ecdev) spin_lock_irq(&tp->lock); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if (!tp->ecdev) { - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irq(&tp->lock); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - memcpy(skb->data, ring + offset, left); - memcpy(skb->data+left, ring, size - left); - } else - memcpy(skb->data, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, - &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_disable(); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_enable(); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev, NULL); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } - else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev, NULL); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue (dev); - - rtl8139_stop_thread(tp); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_module_init (&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.17-orig.c b/devices/8139too-2.6.17-orig.c deleted file mode 100644 index feae7832..00000000 --- a/devices/8139too-2.6.17-orig.c +++ /dev/null @@ -1,2641 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.27" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct work_struct thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (void *_data); -static void rtl8139_tx_timeout_task(void *_data); -static struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pci_name(pdev)); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - printk (KERN_ERR PFX "%s: region #0 not a PIO resource, aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI I/O region size(s), aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - printk (KERN_ERR PFX "%s: region #1 not an MMIO resource, aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI mem region size(s), aborting\n", pci_name(pdev)); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, "8139too"); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev)); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev)); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - printk (KERN_ERR PFX "%s: Chip not responding, ignoring board\n", - pci_name(pdev)); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - printk (KERN_DEBUG PFX "%s: unknown chip version, assuming RTL-8139\n", - pci_name(pdev)); - printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pci_name(pdev), RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - printk(KERN_INFO PFX "pci dev %s (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pci_name(pdev), pdev->vendor, pdev->device, pci_rev); - printk(KERN_INFO PFX "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_WORK(&tp->thread, rtl8139_thread, dev); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#lx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", - dev->name, pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - unsigned long thr_delay = next_tick; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(_data); - } else if (rtnl_trylock()) { - rtl8139_thread_iter (dev, tp, tp->mmio_addr); - rtnl_unlock (); - } else { - /* unlikely race. mitigate with fast poll. */ - thr_delay = HZ / 2; - } - - schedule_delayed_work(&tp->thread, thr_delay); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static void rtl8139_stop_thread(struct rtl8139_private *tp) -{ - if (tp->have_thread) { - cancel_rearming_delayed_work(&tp->thread); - tp->have_thread = 0; - } else - flush_scheduled_work(); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (!tp->have_thread) { - INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); - schedule_delayed_work(&tp->thread, next_tick); - } else - tp->watchdog_fired = 1; - -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - spin_lock_irq(&tp->lock); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irq(&tp->lock); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - memcpy(skb->data, ring + offset, left); - memcpy(skb->data+left, ring, size - left); - } else - memcpy(skb->data, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_disable(); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_enable(); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev, NULL); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue (dev); - - rtl8139_stop_thread(tp); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_module_init (&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.18-ethercat.c b/devices/8139too-2.6.18-ethercat.c deleted file mode 100644 index 992d39e7..00000000 --- a/devices/8139too-2.6.18-ethercat.c +++ /dev/null @@ -1,2790 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.27" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct work_struct thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (void *_data); -static void rtl8139_tx_timeout_task(void *_data); -static struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pci_rev); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_WORK(&tp->thread, rtl8139_thread, dev); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - unsigned long thr_delay = next_tick; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(_data); - } else if (rtnl_trylock()) { - rtl8139_thread_iter (dev, tp, tp->mmio_addr); - rtnl_unlock (); - } else { - /* unlikely race. mitigate with fast poll. */ - thr_delay = HZ / 2; - } - - schedule_delayed_work(&tp->thread, thr_delay); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static void rtl8139_stop_thread(struct rtl8139_private *tp) -{ - if (tp->have_thread) { - cancel_rearming_delayed_work(&tp->thread); - tp->have_thread = 0; - } else - flush_scheduled_work(); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (!tp->ecdev && !tp->have_thread) { - INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); - schedule_delayed_work(&tp->thread, next_tick); - } else - tp->watchdog_fired = 1; - -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } - else { - spin_lock_irqsave(&tp->lock, flags); - - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - memcpy(skb->data, ring + offset, left); - memcpy(skb->data+left, ring, size - left); - } else - memcpy(skb->data, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, - &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_disable(); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_enable(); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev, NULL); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } - else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev, NULL); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue (dev); - - rtl8139_stop_thread(tp); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_module_init (&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.18-orig.c b/devices/8139too-2.6.18-orig.c deleted file mode 100644 index e4f4eaff..00000000 --- a/devices/8139too-2.6.18-orig.c +++ /dev/null @@ -1,2643 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.27" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct work_struct thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (void *_data); -static void rtl8139_tx_timeout_task(void *_data); -static struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pci_rev); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_WORK(&tp->thread, rtl8139_thread, dev); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - unsigned long thr_delay = next_tick; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(_data); - } else if (rtnl_trylock()) { - rtl8139_thread_iter (dev, tp, tp->mmio_addr); - rtnl_unlock (); - } else { - /* unlikely race. mitigate with fast poll. */ - thr_delay = HZ / 2; - } - - schedule_delayed_work(&tp->thread, thr_delay); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static void rtl8139_stop_thread(struct rtl8139_private *tp) -{ - if (tp->have_thread) { - cancel_rearming_delayed_work(&tp->thread); - tp->have_thread = 0; - } else - flush_scheduled_work(); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (!tp->have_thread) { - INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); - schedule_delayed_work(&tp->thread, next_tick); - } else - tp->watchdog_fired = 1; - -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - memcpy(skb->data, ring + offset, left); - memcpy(skb->data+left, ring, size - left); - } else - memcpy(skb->data, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_disable(); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_enable(); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev, NULL); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue (dev); - - rtl8139_stop_thread(tp); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_module_init (&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.19-ethercat.c b/devices/8139too-2.6.19-ethercat.c deleted file mode 100644 index 31d8f615..00000000 --- a/devices/8139too-2.6.19-ethercat.c +++ /dev/null @@ -1,2785 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct work_struct thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (void *_data); -static void rtl8139_tx_timeout_task(void *_data); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pci_rev); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_WORK(&tp->thread, rtl8139_thread, dev); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - unsigned long thr_delay = next_tick; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(_data); - } else if (rtnl_trylock()) { - rtl8139_thread_iter (dev, tp, tp->mmio_addr); - rtnl_unlock (); - } else { - /* unlikely race. mitigate with fast poll. */ - thr_delay = HZ / 2; - } - - schedule_delayed_work(&tp->thread, thr_delay); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static void rtl8139_stop_thread(struct rtl8139_private *tp) -{ - if (tp->have_thread) { - cancel_rearming_delayed_work(&tp->thread); - tp->have_thread = 0; - } else - flush_scheduled_work(); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (!tp->ecdev && !tp->have_thread) { - INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); - schedule_delayed_work(&tp->thread, next_tick); - } else - tp->watchdog_fired = 1; - -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } - else { - spin_lock_irqsave(&tp->lock, flags); - - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - memcpy(skb->data, ring + offset, left); - memcpy(skb->data+left, ring, size - left); - } else - memcpy(skb->data, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, - &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_disable(); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_enable(); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } - else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue (dev); - - rtl8139_stop_thread(tp); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.19-orig.c b/devices/8139too-2.6.19-orig.c deleted file mode 100644 index d02ed51a..00000000 --- a/devices/8139too-2.6.19-orig.c +++ /dev/null @@ -1,2638 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct work_struct thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (void *_data); -static void rtl8139_tx_timeout_task(void *_data); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pci_rev); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_WORK(&tp->thread, rtl8139_thread, dev); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - unsigned long thr_delay = next_tick; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(_data); - } else if (rtnl_trylock()) { - rtl8139_thread_iter (dev, tp, tp->mmio_addr); - rtnl_unlock (); - } else { - /* unlikely race. mitigate with fast poll. */ - thr_delay = HZ / 2; - } - - schedule_delayed_work(&tp->thread, thr_delay); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static void rtl8139_stop_thread(struct rtl8139_private *tp) -{ - if (tp->have_thread) { - cancel_rearming_delayed_work(&tp->thread); - tp->have_thread = 0; - } else - flush_scheduled_work(); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (void *_data) -{ - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (!tp->have_thread) { - INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); - schedule_delayed_work(&tp->thread, next_tick); - } else - tp->watchdog_fired = 1; - -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - memcpy(skb->data, ring + offset, left); - memcpy(skb->data+left, ring, size - left); - } else - memcpy(skb->data, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_disable(); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_enable(); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue (dev); - - rtl8139_stop_thread(tp); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.22-ethercat.c b/devices/8139too-2.6.22-ethercat.c deleted file mode 100644 index ca9578c3..00000000 --- a/devices/8139too-2.6.22-ethercat.c +++ /dev/null @@ -1,2782 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pci_rev); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } - else { - spin_lock_irqsave(&tp->lock, flags); - - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, - &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - else { - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_save(flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_restore(flags); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } - else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue (dev); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.22-orig.c b/devices/8139too-2.6.22-orig.c deleted file mode 100644 index a844b1fe..00000000 --- a/devices/8139too-2.6.22-orig.c +++ /dev/null @@ -1,2634 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - u8 pci_rev; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pci_rev); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_save(flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_restore(flags); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue (dev); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.23-ethercat.c b/devices/8139too-2.6.23-ethercat.c deleted file mode 100644 index 7cd0fc0d..00000000 --- a/devices/8139too-2.6.23-ethercat.c +++ /dev/null @@ -1,2776 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } - else { - spin_lock_irqsave(&tp->lock, flags); - - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_save(flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_restore(flags); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } - else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue (dev); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.23-orig.c b/devices/8139too-2.6.23-orig.c deleted file mode 100644 index f4e4298d..00000000 --- a/devices/8139too-2.6.23-orig.c +++ /dev/null @@ -1,2630 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct net_device_stats stats; - unsigned char *rx_ring; - unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t rx_ring_dma; - dma_addr_t tx_bufs_dma; - signed char phys[4]; /* MII device addresses. */ - char twistie, twist_row, twist_col; /* Twister tune state. */ - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - spinlock_t lock; - spinlock_t rx_lock; - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static int rtl8139_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - - -#define MMIO_FLUSH_AUDIT_COMPLETE 1 -#if MMIO_FLUSH_AUDIT_COMPLETE - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -#else - -/* write MMIO register, then flush */ -#define RTL_W8 RTL_W8_F -#define RTL_W16 RTL_W16_F -#define RTL_W32 RTL_W32_F - -#endif /* MMIO_FLUSH_AUDIT_COMPLETE */ - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - dev->poll = rtl8139_poll; - dev->weight = 64; - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma); - tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct net_device *dev, int *budget) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int orig_budget = min(*budget, dev->quota); - int done = 1; - - spin_lock(&tp->rx_lock); - if (likely(RTL_R16(IntrStatus) & RxAckBits)) { - int work_done; - - work_done = rtl8139_rx(dev, tp, orig_budget); - if (likely(work_done > 0)) { - *budget -= work_done; - dev->quota -= work_done; - done = (work_done < orig_budget); - } - } - - if (done) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - local_irq_save(flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev); - local_irq_restore(flags); - } - spin_unlock(&tp->rx_lock); - - return !done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule (dev); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue (dev); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_stats_count(struct net_device *dev) -{ - return RTL_NUM_STATS; -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_stats_count = rtl8139_get_stats_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.24-ethercat.c b/devices/8139too-2.6.24-ethercat.c deleted file mode 100644 index 2dbaf721..00000000 --- a/devices/8139too-2.6.24-ethercat.c +++ /dev/null @@ -1,2769 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - struct net_device_stats stats; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } - else { - spin_lock_irqsave(&tp->lock, flags); - - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue (dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.24-orig.c b/devices/8139too-2.6.24-orig.c deleted file mode 100644 index eef6fecf..00000000 --- a/devices/8139too-2.6.24-orig.c +++ /dev/null @@ -1,2624 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - struct net_device_stats stats; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.25-ethercat.c b/devices/8139too-2.6.25-ethercat.c deleted file mode 100644 index 8bb44e06..00000000 --- a/devices/8139too-2.6.25-ethercat.c +++ /dev/null @@ -1,2769 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - struct net_device_stats stats; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } - else { - spin_lock_irqsave(&tp->lock, flags); - - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue (dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.25-orig.c b/devices/8139too-2.6.25-orig.c deleted file mode 100644 index be6e9184..00000000 --- a/devices/8139too-2.6.25-orig.c +++ /dev/null @@ -1,2624 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - struct net_device_stats stats; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.26-ethercat.c b/devices/8139too-2.6.26-ethercat.c deleted file mode 100644 index 233f3928..00000000 --- a/devices/8139too-2.6.26-ethercat.c +++ /dev/null @@ -1,2774 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - struct net_device_stats stats; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } - else { - spin_lock_irqsave(&tp->lock, flags); - - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - else { - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - /* - * use _nosync() variant - might be used by netconsole - * from atomic contexts: - */ - disable_irq_nosync(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue (dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.26-orig.c b/devices/8139too-2.6.26-orig.c deleted file mode 100644 index 646af9ae..00000000 --- a/devices/8139too-2.6.26-orig.c +++ /dev/null @@ -1,2628 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ -#ifdef CONFIG_8139TOO_PIO -#define USE_IO_OPS 1 -#endif - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - struct net_device_stats stats; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - -#ifdef USE_IO_OPS - if (tp->mmio_addr) - ioport_unmap (tp->mmio_addr); -#else - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); -#endif /* USE_IO_OPS */ - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -#ifdef USE_IO_OPS - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#else - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } -#endif - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - -#ifdef USE_IO_OPS - ioaddr = ioport_map(pio_start, pio_len); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->mmio_addr = ioaddr; - tp->regs_len = pio_len; -#else - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = (long) ioaddr; - tp->mmio_addr = ioaddr; - tp->regs_len = mmio_len; -#endif /* USE_IO_OPS */ - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - tp->stats.tx_errors++; - if (txstatus & TxAborted) { - tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - tp->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - tp->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - tp->stats.tx_fifo_errors++; - } - tp->stats.collisions += (txstatus >> 24) & 15; - tp->stats.tx_bytes += txstatus & 0x7ff; - tp->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - tp->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - tp->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - tp->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - tp->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - tp->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - tp->stats.rx_errors++; - - if (status & PCSTimeout) - tp->stats.rx_length_errors++; - if (status & RxUnderrun) - tp->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - /* - * use _nosync() variant - might be used by netconsole - * from atomic contexts: - */ - disable_irq_nosync(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - synchronize_irq (dev->irq); /* racy, but that's ok here */ - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -/* TODO: we are too slack to do reg dumping for pio, for now */ -#ifdef CONFIG_8139TOO_PIO -#define rtl8139_get_regs_len NULL -#define rtl8139_get_regs NULL -#else -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} -#endif /* CONFIG_8139TOO_MMIO */ - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &tp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.27-ethercat.c b/devices/8139too-2.6.27-ethercat.c deleted file mode 100644 index 84748c24..00000000 --- a/devices/8139too-2.6.27-ethercat.c +++ /dev/null @@ -1,2774 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } else { - spin_lock_irqsave(&tp->lock, flags); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.27-orig.c b/devices/8139too-2.6.27-orig.c deleted file mode 100644 index 8a5b0d29..00000000 --- a/devices/8139too-2.6.27-orig.c +++ /dev/null @@ -1,2632 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pdev->revision); - dev_info(&pdev->dev, - "Use the \"8139cp\" driver for improved performance and stability.\n"); - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = dev_alloc_skb (pkt_size + 2); - if (likely(skb)) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.28-ethercat.c b/devices/8139too-2.6.28-ethercat.c deleted file mode 100644 index c1ef9a3a..00000000 --- a/devices/8139too-2.6.28-ethercat.c +++ /dev/null @@ -1,2774 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - } else { - spin_lock_irqsave(&tp->lock, flags); - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.28-orig.c b/devices/8139too-2.6.28-orig.c deleted file mode 100644 index 63f906b0..00000000 --- a/devices/8139too-2.6.28-orig.c +++ /dev/null @@ -1,2637 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static int __devinit rtl8139_init_board (struct pci_dev *pdev, - struct net_device **dev_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - *dev_out = NULL; - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return -ENOMEM; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - *dev_out = dev; - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return rc; -} - - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - DECLARE_MAC_BUF(mac); - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - i = rtl8139_init_board (pdev, &dev); - if (i < 0) - return i; - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->open = rtl8139_open; - dev->hard_start_xmit = rtl8139_start_xmit; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - dev->stop = rtl8139_close; - dev->get_stats = rtl8139_get_stats; - dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = netdev_ioctl; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->tx_timeout = rtl8139_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8139_poll_controller; -#endif - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%s, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - print_mac(mac, dev->dev_addr), - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(dev, napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(dev, &tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(dev, &tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.29-ethercat.c b/devices/8139too-2.6.29-ethercat.c deleted file mode 100644 index 3576e8af..00000000 --- a/devices/8139too-2.6.29-ethercat.c +++ /dev/null @@ -1,2772 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - - if (!tp->ecdev) { - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - } else { - spin_lock_irqsave(&tp->lock, flags); - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (netif_rx_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(&tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (np->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.29-orig.c b/devices/8139too-2.6.29-orig.c deleted file mode 100644 index a5b24202..00000000 --- a/devices/8139too-2.6.29-orig.c +++ /dev/null @@ -1,2636 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - DPRINTK("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - printk (KERN_INFO "%s: %s at 0x%lx, " - "%pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - tp->cur_rx = 0; - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - DPRINTK("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (netif_rx_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(&tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&np->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[np->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&np->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *np = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *np; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - np = netdev_priv(dev); - return np->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *np; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - np = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *np = netdev_priv(dev); - - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.31-ethercat.c b/devices/8139too-2.6.31-ethercat.c deleted file mode 100644 index ff991c6b..00000000 --- a/devices/8139too-2.6.31-ethercat.c +++ /dev/null @@ -1,2785 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (!tp->ecdev) { - if (netif_msg_ifup(tp)) - pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - pr_info("%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - pr_info("%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - pr_debug("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - pr_debug("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", - dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - } else { - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - pr_debug("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - pr_debug("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __napi_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (tp->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.31-orig.c b/devices/8139too-2.6.31-orig.c deleted file mode 100644 index 0e2ba21d..00000000 --- a/devices/8139too-2.6.31-orig.c +++ /dev/null @@ -1,2645 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - pr_info("%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - pr_info("%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - pr_debug("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - pr_debug("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", - dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - pr_debug("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - pr_debug("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __napi_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.32-ethercat.c b/devices/8139too-2.6.32-ethercat.c deleted file mode 100644 index 7e893abf..00000000 --- a/devices/8139too-2.6.32-ethercat.c +++ /dev/null @@ -1,2784 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (!tp->ecdev) { - if (netif_msg_ifup(tp)) - pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - pr_info("%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - pr_info("%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - pr_debug("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - pr_debug("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", - dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags = 0; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) { - dev_kfree_skb(skb); - } - } else { - if (!tp->ecdev) { - dev_kfree_skb(skb); - } - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - if (!tp->ecdev) { - spin_lock_irqsave(&tp->lock, flags); - } - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if (!tp->ecdev) { - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - pr_debug("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - pr_debug("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __napi_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (tp->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.32-orig.c b/devices/8139too-2.6.32-orig.c deleted file mode 100644 index 4a362875..00000000 --- a/devices/8139too-2.6.32-orig.c +++ /dev/null @@ -1,2646 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - pr_info("%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - pr_info("%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - pr_debug("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - pr_debug("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", - dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - pr_debug("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - pr_debug("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __napi_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.33-ethercat.c b/devices/8139too-2.6.33-ethercat.c deleted file mode 100644 index d13d708c..00000000 --- a/devices/8139too-2.6.33-ethercat.c +++ /dev/null @@ -1,2790 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (!tp->ecdev) { - if (netif_msg_ifup(tp)) - pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = ((mii_lpa & LPA_100FULL) || - (mii_lpa & 0x01C0) == 0x0040); - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - pr_info("%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - pr_info("%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - pr_debug("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - pr_debug("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", - dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - if (tp->ecdev) { - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - } else { - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - pr_debug("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - pr_debug("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb_ip_align(dev, pkt_size); - if (likely(skb)) { - -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __napi_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - /* - * use _nosync() variant - might be used by netconsole - * from atomic contexts: - */ - disable_irq_nosync(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (tp->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.33-orig.c b/devices/8139too-2.6.33-orig.c deleted file mode 100644 index 3b8ff0d0..00000000 --- a/devices/8139too-2.6.33-orig.c +++ /dev/null @@ -1,2649 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static struct pci_device_id rtl8139_pci_tbl[] = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (netif_msg_ifup(tp)) - pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = ((mii_lpa & LPA_100FULL) || - (mii_lpa & 0x01C0) == 0x0040); - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - pr_info("%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - pr_info("%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - pr_debug("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - pr_debug("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", - dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - pr_debug("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - pr_debug("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while (netif_running(dev) && received < budget && - (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb_ip_align(dev, pkt_size); - if (likely(skb)) { -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __napi_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - /* - * use _nosync() variant - might be used by netconsole - * from atomic contexts: - */ - disable_irq_nosync(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.34-ethercat.c b/devices/8139too-2.6.34-ethercat.c deleted file mode 100644 index 47e8788e..00000000 --- a/devices/8139too-2.6.34-ethercat.c +++ /dev/null @@ -1,2786 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (!tp->ecdev) { - if (netif_msg_ifup(tp)) - pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - pr_info("%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - pr_info("%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - pr_debug("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - pr_debug("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", - dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - } else { - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - pr_debug("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - pr_debug("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __napi_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (tp->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; - u32 tmp; - - pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.34-orig.c b/devices/8139too-2.6.34-orig.c deleted file mode 100644 index f0d23de3..00000000 --- a/devices/8139too-2.6.34-orig.c +++ /dev/null @@ -1,2620 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if (unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - pr_debug("about to register device named %s (%p)...\n", - dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n", - board_info[ent->driver_data].name, - dev->base_addr, dev->dev_addr, dev->irq); - - netdev_dbg(dev, "Identified 8139 chip type '%s'\n", - rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - netdev_info(dev, "MII transceiver %d status 0x%04x advertising %04x\n", - phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - netdev_info(dev, "No MII transceivers found! Assuming SYM transceiver\n"); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - netdev_info(dev, "Media type forced to Full Duplex\n"); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - netdev_info(dev, " Forcing %dMbps %s-duplex operation\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - netif_dbg(tp, ifup, dev, - "%s() ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n", - __func__, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = ((mii_lpa & LPA_100FULL) || - (mii_lpa & 0x01C0) == 0x0040); - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n", - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - netdev_info(dev, "media is unconnected, link down, or incompatible connection\n"); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - netdev_dbg(dev, "Media selection tick, Link partner %04x\n", - RTL_R16(NWayLPAR)); - netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x\n", - RTL_R16(IntrMask), RTL_R16(IntrStatus)); - netdev_dbg(dev, "Chip config %02x %02x\n", - RTL_R8(Config0), RTL_R8(Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - netdev_dbg(dev, "Transmit timeout, status %02x %04x %04x media %02x\n", - RTL_R8(ChipCmd), RTL_R16(IntrStatus), - RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - netdev_dbg(dev, "Tx queue start entry %ld dirty entry %ld\n", - tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - netdev_dbg(dev, "Tx descriptor %d is %08lx%s\n", - i, RTL_R32(TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - netif_dbg(tp, tx_queued, dev, "Queued Tx packet size %u to slot %d\n", - len, entry); - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - netif_dbg(tp, tx_err, dev, "Transmit error, Tx status %08x\n", - txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - netdev_err(dev, "Out-of-sync dirty pointer, %ld vs. %ld\n", - dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - netif_dbg(tp, rx_err, dev, "Ethernet frame had errors, status %08x\n", - rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n", - rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - netdev_warn(dev, "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - netdev_warn(dev, "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - netdev_dbg(dev, "In %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", - __func__, (u16)cur_rx, - RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); - - while (netif_running(dev) && received < budget && - (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - netif_dbg(tp, rx_status, dev, "%s() status %04x, size %04x, cur %04x\n", - __func__, rx_status, rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - print_hex_dump(KERN_DEBUG, "Frame contents: ", - DUMP_PREFIX_OFFSET, 16, 1, - &rx_ring[ring_offset], 70, true); -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - netdev_dbg(dev, "hung FIFO. Reset\n"); - rx_size = 0; - goto no_early_rx; - } - netif_dbg(tp, intr, dev, "fifo copy in progress\n"); - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb_ip_align(dev, pkt_size); - if (likely(skb)) { -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - netdev_warn(dev, "Memory squeeze, dropping packet\n"); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - netdev_dbg(dev, "Done %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", - __func__, cur_rx, - RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - netdev_dbg(dev, "Abnormal interrupt, status %08x\n", status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - netdev_err(dev, "PCI Bus error %04x\n", pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - __napi_complete(napi); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - netdev_dbg(dev, "exiting interrupt, intr_status=%#4.4x\n", - RTL_R16(IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - netif_dbg(tp, ifdown, dev, "Shutting down ethercard, status was 0x%04x\n", - RTL_R16(IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp; - - netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08lx\n", - dev->flags, RTL_R32(RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(mclist, dev) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.35-ethercat.c b/devices/8139too-2.6.35-ethercat.c deleted file mode 100644 index 29c63876..00000000 --- a/devices/8139too-2.6.35-ethercat.c +++ /dev/null @@ -1,2782 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if(unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static int rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - i = 0; - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - if (!tp->ecdev) { - if (netif_msg_ifup(tp)) - pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = (mii_lpa & LPA_100FULL) - || (mii_lpa & 0x01C0) == 0x0040; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - pr_info("%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - pr_info("%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - pr_debug("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - pr_debug("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", - dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) dev_kfree_skb(skb); - } else { - if (!tp->ecdev) dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - if (tp->ecdev) { - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - tp->cur_tx++; - } else { - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - if (netif_msg_tx_queued(tp)) - pr_debug("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); - } - - return 0; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - pr_debug("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - __napi_complete(napi); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) spin_unlock (&tp->lock); - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (tp->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp; - - pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.35-orig.c b/devices/8139too-2.6.35-orig.c deleted file mode 100644 index 97d8068b..00000000 --- a/devices/8139too-2.6.35-orig.c +++ /dev/null @@ -1,2619 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if (unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - i = 0; - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - pr_debug("about to register device named %s (%p)...\n", - dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n", - board_info[ent->driver_data].name, - dev->base_addr, dev->dev_addr, dev->irq); - - netdev_dbg(dev, "Identified 8139 chip type '%s'\n", - rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - netdev_info(dev, "MII transceiver %d status 0x%04x advertising %04x\n", - phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - netdev_info(dev, "No MII transceivers found! Assuming SYM transceiver\n"); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - netdev_info(dev, "Media type forced to Full Duplex\n"); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - netdev_info(dev, " Forcing %dMbps %s-duplex operation\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - netif_dbg(tp, ifup, dev, - "%s() ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n", - __func__, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = ((mii_lpa & LPA_100FULL) || - (mii_lpa & 0x01C0) == 0x0040); - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n", - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - netdev_info(dev, "media is unconnected, link down, or incompatible connection\n"); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - netdev_dbg(dev, "Media selection tick, Link partner %04x\n", - RTL_R16(NWayLPAR)); - netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x\n", - RTL_R16(IntrMask), RTL_R16(IntrStatus)); - netdev_dbg(dev, "Chip config %02x %02x\n", - RTL_R8(Config0), RTL_R8(Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - netdev_dbg(dev, "Transmit timeout, status %02x %04x %04x media %02x\n", - RTL_R8(ChipCmd), RTL_R16(IntrStatus), - RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - netdev_dbg(dev, "Tx queue start entry %ld dirty entry %ld\n", - tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - netdev_dbg(dev, "Tx descriptor %d is %08lx%s\n", - i, RTL_R32(TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - netif_dbg(tp, tx_queued, dev, "Queued Tx packet size %u to slot %d\n", - len, entry); - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - netif_dbg(tp, tx_err, dev, "Transmit error, Tx status %08x\n", - txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - netdev_err(dev, "Out-of-sync dirty pointer, %ld vs. %ld\n", - dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - netif_dbg(tp, rx_err, dev, "Ethernet frame had errors, status %08x\n", - rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n", - rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - netdev_warn(dev, "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - netdev_warn(dev, "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - netdev_dbg(dev, "In %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", - __func__, (u16)cur_rx, - RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); - - while (netif_running(dev) && received < budget && - (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - netif_dbg(tp, rx_status, dev, "%s() status %04x, size %04x, cur %04x\n", - __func__, rx_status, rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - print_hex_dump(KERN_DEBUG, "Frame contents: ", - DUMP_PREFIX_OFFSET, 16, 1, - &rx_ring[ring_offset], 70, true); -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - netdev_dbg(dev, "hung FIFO. Reset\n"); - rx_size = 0; - goto no_early_rx; - } - netif_dbg(tp, intr, dev, "fifo copy in progress\n"); - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb_ip_align(dev, pkt_size); - if (likely(skb)) { -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - netdev_warn(dev, "Memory squeeze, dropping packet\n"); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - netdev_dbg(dev, "Done %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", - __func__, cur_rx, - RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - netdev_dbg(dev, "Abnormal interrupt, status %08x\n", status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - netdev_err(dev, "PCI Bus error %04x\n", pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - __napi_complete(napi); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - netdev_dbg(dev, "exiting interrupt, intr_status=%#4.4x\n", - RTL_R16(IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - netif_dbg(tp, ifdown, dev, "Shutting down ethercard, status was 0x%04x\n", - RTL_R16(IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp; - - netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08lx\n", - dev->flags, RTL_R32(RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.36-ethercat.c b/devices/8139too-2.6.36-ethercat.c deleted file mode 100644 index 891b8662..00000000 --- a/devices/8139too-2.6.36-ethercat.c +++ /dev/null @@ -1,2788 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if (unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ioread32 (ioaddr + (reg)) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - i = 0; - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%x\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) { - free_irq(dev->irq, dev); - } - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - if (!tp->ecdev) { - netif_start_queue (dev); - } - - netif_dbg(tp, ifup, dev, - "%s() ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n", - __func__, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - if (!tp->ecdev) { - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) { - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); - } -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = ((mii_lpa & LPA_100FULL) || - (mii_lpa & 0x01C0) == 0x0040); - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n", - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - netdev_info(dev, "media is unconnected, link down, or incompatible connection\n"); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - netdev_dbg(dev, "Media selection tick, Link partner %04x\n", - RTL_R16(NWayLPAR)); - netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x\n", - RTL_R16(IntrMask), RTL_R16(IntrStatus)); - netdev_dbg(dev, "Chip config %02x %02x\n", - RTL_R8(Config0), RTL_R8(Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - netdev_dbg(dev, "Transmit timeout, status %02x %04x %04x media %02x\n", - RTL_R8(ChipCmd), RTL_R16(IntrStatus), - RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - netdev_dbg(dev, "Tx queue start entry %ld dirty entry %ld\n", - tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - netdev_dbg(dev, "Tx descriptor %d is %08x%s\n", - i, RTL_R32(TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags = 0; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) { - dev_kfree_skb(skb); - } - } else { - if (!tp->ecdev) { - dev_kfree_skb(skb); - } - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - if (!tp->ecdev) { - spin_lock_irqsave(&tp->lock, flags); - } - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - tp->cur_tx++; - - if (!tp->ecdev) { - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - } - - netif_dbg(tp, tx_queued, dev, "Queued Tx packet size %u to slot %d\n", - len, entry); - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - netif_dbg(tp, tx_err, dev, "Transmit error, Tx status %08x\n", - txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) { - netif_wake_queue (dev); - } - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - __napi_complete(napi); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) { - spin_unlock (&tp->lock); - } - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (tp->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp; - - netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08x\n", - dev->flags, RTL_R32(RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.36-orig.c b/devices/8139too-2.6.36-orig.c deleted file mode 100644 index f5166dcc..00000000 --- a/devices/8139too-2.6.36-orig.c +++ /dev/null @@ -1,2619 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if (unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ioread32 (ioaddr + (reg)) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - i = 0; - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%x\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - pr_debug("about to register device named %s (%p)...\n", - dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n", - board_info[ent->driver_data].name, - dev->base_addr, dev->dev_addr, dev->irq); - - netdev_dbg(dev, "Identified 8139 chip type '%s'\n", - rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - netdev_info(dev, "MII transceiver %d status 0x%04x advertising %04x\n", - phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - netdev_info(dev, "No MII transceivers found! Assuming SYM transceiver\n"); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - netdev_info(dev, "Media type forced to Full Duplex\n"); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - netdev_info(dev, " Forcing %dMbps %s-duplex operation\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - netif_dbg(tp, ifup, dev, - "%s() ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n", - __func__, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = ((mii_lpa & LPA_100FULL) || - (mii_lpa & 0x01C0) == 0x0040); - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n", - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - netdev_info(dev, "media is unconnected, link down, or incompatible connection\n"); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - netdev_dbg(dev, "Media selection tick, Link partner %04x\n", - RTL_R16(NWayLPAR)); - netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x\n", - RTL_R16(IntrMask), RTL_R16(IntrStatus)); - netdev_dbg(dev, "Chip config %02x %02x\n", - RTL_R8(Config0), RTL_R8(Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - netdev_dbg(dev, "Transmit timeout, status %02x %04x %04x media %02x\n", - RTL_R8(ChipCmd), RTL_R16(IntrStatus), - RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - netdev_dbg(dev, "Tx queue start entry %ld dirty entry %ld\n", - tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - netdev_dbg(dev, "Tx descriptor %d is %08x%s\n", - i, RTL_R32(TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - netif_dbg(tp, tx_queued, dev, "Queued Tx packet size %u to slot %d\n", - len, entry); - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - netif_dbg(tp, tx_err, dev, "Transmit error, Tx status %08x\n", - txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - netdev_err(dev, "Out-of-sync dirty pointer, %ld vs. %ld\n", - dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - netif_dbg(tp, rx_err, dev, "Ethernet frame had errors, status %08x\n", - rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n", - rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - netdev_warn(dev, "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - netdev_warn(dev, "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - netdev_dbg(dev, "In %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", - __func__, (u16)cur_rx, - RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); - - while (netif_running(dev) && received < budget && - (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - netif_dbg(tp, rx_status, dev, "%s() status %04x, size %04x, cur %04x\n", - __func__, rx_status, rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - print_hex_dump(KERN_DEBUG, "Frame contents: ", - DUMP_PREFIX_OFFSET, 16, 1, - &rx_ring[ring_offset], 70, true); -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - netdev_dbg(dev, "hung FIFO. Reset\n"); - rx_size = 0; - goto no_early_rx; - } - netif_dbg(tp, intr, dev, "fifo copy in progress\n"); - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb_ip_align(dev, pkt_size); - if (likely(skb)) { -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - netdev_warn(dev, "Memory squeeze, dropping packet\n"); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - netdev_dbg(dev, "Done %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", - __func__, cur_rx, - RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - netdev_dbg(dev, "Abnormal interrupt, status %08x\n", status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - netdev_err(dev, "PCI Bus error %04x\n", pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - __napi_complete(napi); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - netdev_dbg(dev, "exiting interrupt, intr_status=%#4.4x\n", - RTL_R16(IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - netif_dbg(tp, ifdown, dev, "Shutting down ethercard, status was 0x%04x\n", - RTL_R16(IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp; - - netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08x\n", - dev->flags, RTL_R32(RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.37-ethercat.c b/devices/8139too-2.6.37-ethercat.c deleted file mode 100644 index 4b458828..00000000 --- a/devices/8139too-2.6.37-ethercat.c +++ /dev/null @@ -1,2790 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for RTL8139-compatible NICs. -*/ - -/*****************************************************************************/ - -/* - Former documentation: - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define DRV_NAME "ec_8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8139_DRIVER_NAME DRV_NAME \ - " EtherCAT-capable Fast Ethernet driver " \ - DRV_VERSION ", master " EC_MASTER_VERSION - -#define PFX DRV_NAME ": " - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if (unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; - - ec_device_t *ecdev; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -void ec_poll(struct net_device *); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ioread32 (ioaddr + (reg)) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end __attribute__ ((unused)), pio_flags, - pio_len; - unsigned long mmio_start __attribute__ ((unused)), - mmio_end __attribute__ ((unused)), mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - i = 0; - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%x\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - } - - pci_set_drvdata (pdev, dev); - - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); - - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - if (tp->ecdev) { - i = ecdev_open(tp->ecdev); - if (i) { - ecdev_withdraw(tp->ecdev); - goto err_out; - } - } - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - assert (dev != NULL); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } - else { - unregister_netdev (dev); - } - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8139_interrupt, - IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - } - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - if (!tp->ecdev) { - free_irq(dev->irq, dev); - } - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - if (!tp->ecdev) { - netif_start_queue (dev); - } - - netif_dbg(tp, ifup, dev, - "%s() ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n", - __func__, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - if (!tp->ecdev) { - rtl8139_start_thread(tp); - } - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->ecdev) { - void __iomem *ioaddr = tp->mmio_addr; - u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; - ecdev_set_link(tp->ecdev, state ? 1 : 0); - } - else { - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - if (!tp->ecdev) { - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); - } -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = ((mii_lpa & LPA_100FULL) || - (mii_lpa & 0x01C0) == 0x0040); - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n", - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - netdev_info(dev, "media is unconnected, link down, or incompatible connection\n"); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - netdev_dbg(dev, "Media selection tick, Link partner %04x\n", - RTL_R16(NWayLPAR)); - netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x\n", - RTL_R16(IntrMask), RTL_R16(IntrStatus)); - netdev_dbg(dev, "Chip config %02x %02x\n", - RTL_R8(Config0), RTL_R8(Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - netdev_dbg(dev, "Transmit timeout, status %02x %04x %04x media %02x\n", - RTL_R8(ChipCmd), RTL_R16(IntrStatus), - RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - netdev_dbg(dev, "Tx queue start entry %ld dirty entry %ld\n", - tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - netdev_dbg(dev, "Tx descriptor %d is %08x%s\n", - i, RTL_R32(TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - if (tp->ecdev) { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - else { - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); - } -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->ecdev && !tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags = 0; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - if (!tp->ecdev) { - dev_kfree_skb(skb); - } - } else { - if (!tp->ecdev) { - dev_kfree_skb(skb); - } - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - if (!tp->ecdev) { - spin_lock_irqsave(&tp->lock, flags); - } - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - tp->cur_tx++; - - if (!tp->ecdev) { - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - } - - netif_dbg(tp, tx_queued, dev, "Queued Tx packet size %u to slot %d\n", - len, entry); - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - netif_dbg(tp, tx_err, dev, "Transmit error, Tx status %08x\n", - txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - if (!tp->ecdev) { - netif_wake_queue (dev); - } - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - pr_debug("init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - while ((tp->ecdev || netif_running(dev)) - && received < budget - && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - if (!tp->ecdev) { - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); - } -#if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); - rx_size = 0; - goto no_early_rx; - } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - if (tp->ecdev) { - ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size); - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN); - if (likely(skb)) { - skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */ -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - } - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - __napi_complete(napi); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -void ec_poll(struct net_device *dev) -{ - rtl8139_interrupt(0, dev); -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - if (tp->ecdev) { - status = RTL_R16 (IntrStatus); - } - else { - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - } - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - if (!tp->ecdev) { - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (tp->ecdev) { - /* EtherCAT device: Just receive all frames */ - rtl8139_rx(dev, tp, 100); // FIXME - } else { - /* Mark for polling */ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - if (!tp->ecdev) { - spin_unlock (&tp->lock); - } - - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev) { - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - } else { - netif_stop_queue(dev); - napi_disable(&tp->napi); - - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - } - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (tp->ecdev || !netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (tp->ecdev || netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp; - - netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08x\n", - dev->flags, RTL_R32(RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (tp->ecdev || !netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - - pci_restore_state (pdev); - if (tp->ecdev || !netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/8139too-2.6.37-orig.c b/devices/8139too-2.6.37-orig.c deleted file mode 100644 index f5166dcc..00000000 --- a/devices/8139too-2.6.37-orig.c +++ /dev/null @@ -1,2619 +0,0 @@ -/* - - 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - - Maintained by Jeff Garzik - Copyright 2000-2002 Jeff Garzik - - Much code comes from Donald Becker's rtl8139.c driver, - versions 1.13 and older. This driver was originally based - on rtl8139.c version 1.07. Header of rtl8139.c version 1.13: - - ---------- - - Written 1997-2001 by Donald Becker. - This software may be used and distributed according to the - terms of the GNU General Public License (GPL), incorporated - herein by reference. Drivers based on or derived from this - code fall under the GPL and must retain the authorship, - copyright and license notice. This file is not a complete - program and may only be used when the entire operating - system is licensed under the GPL. - - This driver is for boards based on the RTL8129 and RTL8139 - PCI ethernet chips. - - The author may be reached as becker@scyld.com, or C/O Scyld - Computing Corporation 410 Severn Ave., Suite 210 Annapolis - MD 21403 - - Support and updates available at - http://www.scyld.com/network/rtl8139.html - - Twister-tuning table provided by Kinston - . - - ---------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - Contributors: - - Donald Becker - he wrote the original driver, kudos to him! - (but please don't e-mail him for support, this isn't his driver) - - Tigran Aivazian - bug fixes, skbuff free cleanup - - Martin Mares - suggestions for PCI cleanup - - David S. Miller - PCI DMA and softnet updates - - Ernst Gill - fixes ported from BSD driver - - Daniel Kobras - identified specific locations of - posted MMIO write bugginess - - Gerard Sharp - bug fix, testing and feedback - - David Ford - Rx ring wrap fix - - Dan DeMaggio - swapped RTL8139 cards with me, and allowed me - to find and fix a crucial bug on older chipsets. - - Donald Becker/Chris Butterworth/Marcus Westergren - - Noticed various Rx packet size-related buglets. - - Santiago Garcia Mantinan - testing and feedback - - Jens David - 2.2.x kernel backports - - Martin Dennett - incredibly helpful insight on undocumented - features of the 8139 chips - - Jean-Jacques Michel - bug fix - - Tobias Ringström - Rx interrupt status checking suggestion - - Andrew Morton - Clear blocked signals, avoid - buffer overrun setting current->comm. - - Kalle Olavi Niemitalo - Wake-on-LAN ioctls - - Robert Kuebel - Save kernel thread from dying on any signal. - - Submitting bug reports: - - "rtl8139-diag -mmmaaavvveefN" output - enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - -*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define DRV_NAME "8139too" -#define DRV_VERSION "0.9.28" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION - -/* Default Message level */ -#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ - NETIF_MSG_PROBE | \ - NETIF_MSG_LINK) - - -/* define to 1, 2 or 3 to enable copious debugging info */ -#define RTL8139_DEBUG 0 - -/* define to 1 to disable lightweight runtime debugging checks */ -#undef RTL8139_NDEBUG - - -#ifdef RTL8139_NDEBUG -# define assert(expr) do {} while (0) -#else -# define assert(expr) \ - if (unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif - - -/* A few user-configurable values. */ -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; - -/* Whether to use MMIO or PIO. Default to MMIO. */ -#ifdef CONFIG_8139TOO_PIO -static int use_io = 1; -#else -static int use_io = 0; -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; - -/* bitmapped message enable number */ -static int debug = -1; - -/* - * Receive ring size - * Warning: 64K ring has hardware issues and may lock up. - */ -#if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 0 /* 8K ring */ -#else -#define RX_BUF_IDX 2 /* 32K ring */ -#endif -#define RX_BUF_LEN (8192 << RX_BUF_IDX) -#define RX_BUF_PAD 16 -#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ - -#if RX_BUF_LEN == 65536 -#define RX_BUF_TOT_LEN RX_BUF_LEN -#else -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#endif - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - - -enum { - HAS_MII_XCVR = 0x010000, - HAS_CHIP_XCVR = 0x020000, - HAS_LNK_CHNG = 0x040000, -}; - -#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ -#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8139B_IO_SIZE 256 - -#define RTL8129_CAPS HAS_MII_XCVR -#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG) - -typedef enum { - RTL8139 = 0, - RTL8129, -} board_t; - - -/* indexed by board_t, above */ -static const struct { - const char *name; - u32 hw_flags; -} board_info[] __devinitdata = { - { "RealTek RTL8139", RTL8139_CAPS }, - { "RealTek RTL8129", RTL8129_CAPS }, -}; - - -static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { - {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - -#ifdef CONFIG_SH_SECUREEDGE5410 - /* Bogus 8139 silicon reports 8129 without external PROM :-( */ - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, -#endif -#ifdef CONFIG_8139TOO_8129 - {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, -#endif - - /* some crazy cards report invalid vendor ids like - * 0x0001 here. The other ids are valid and constant, - * so we simply don't match on the main vendor id. - */ - {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, - - {0,} -}; -MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); - -static struct { - const char str[ETH_GSTRING_LEN]; -} ethtool_stats_keys[] = { - { "early_rx" }, - { "tx_buf_mapped" }, - { "tx_timeouts" }, - { "rx_lost_in_ring" }, -}; - -/* The rest of these values should never change. */ - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - TimerInt = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - TxSummary = 0x60, - BasicModeCtrl = 0x62, - BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, - /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ -}; - -enum ClearBitMasks { - MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), -}; - -enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, -}; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr = 0x8000, - PCSTimeout = 0x4000, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - RxAckBits = RxFIFOOver | RxOverflow | RxOK, -}; - -enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, - TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, - TxCarrierLost = 0x80000000, -}; -enum RxStatusBits { - RxMulticast = 0x8000, - RxPhysical = 0x4000, - RxBroadcast = 0x2000, - RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -}; - -/* Bits in TxConfig. */ -enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */ - - TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ -}; - -/* Bits in Config1 */ -enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ - Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ -}; - -/* Bits in Config3 */ -enum Config3Bits { - Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ - Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ - Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ - Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ - Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ - Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ - Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ - Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ -}; - -/* Bits in Config4 */ -enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ -}; - -/* Bits in Config5 */ -enum Config5Bits { - Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ - Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ - Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ - Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */ - Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ - Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ - Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ -}; - -enum RxConfigBits { - /* rx fifo threshold */ - RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), - - /* Max DMA burst */ - RxCfgDMAShift = 8, - RxCfgDMAUnlimited = (7 << RxCfgDMAShift), - - /* rx ring buffer length */ - RxCfgRcv8K = 0, - RxCfgRcv16K = (1 << 11), - RxCfgRcv32K = (1 << 12), - RxCfgRcv64K = (1 << 11) | (1 << 12), - - /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ - RxNoWrap = (1 << 7), -}; - -/* Twister tuning parameters from RealTek. - Completely undocumented, but required to tune bad links on some boards. */ -enum CSCRBits { - CSCR_LinkOKBit = 0x0400, - CSCR_LinkChangeBit = 0x0800, - CSCR_LinkStatusBits = 0x0f000, - CSCR_LinkDownOffCmd = 0x003c0, - CSCR_LinkDownCmd = 0x0f3c0, -}; - -enum Cfg9346Bits { - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, -}; - -typedef enum { - CH_8139 = 0, - CH_8139_K, - CH_8139A, - CH_8139A_G, - CH_8139B, - CH_8130, - CH_8139C, - CH_8100, - CH_8100B_8139D, - CH_8101, -} chip_t; - -enum chip_flags { - HasHltClk = (1 << 0), - HasLWake = (1 << 1), -}; - -#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) - -/* directly indexed by chip_t, above */ -static const struct { - const char *name; - u32 version; /* from RTL8139C/RTL8139D docs */ - u32 flags; -} rtl_chip_info[] = { - { "RTL-8139", - HW_REVID(1, 0, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139 rev K", - HW_REVID(1, 1, 0, 0, 0, 0, 0), - HasHltClk, - }, - - { "RTL-8139A", - HW_REVID(1, 1, 1, 0, 0, 0, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139A rev G", - HW_REVID(1, 1, 1, 0, 0, 1, 0), - HasHltClk, /* XXX undocumented? */ - }, - - { "RTL-8139B", - HW_REVID(1, 1, 1, 1, 0, 0, 0), - HasLWake, - }, - - { "RTL-8130", - HW_REVID(1, 1, 1, 1, 1, 0, 0), - HasLWake, - }, - - { "RTL-8139C", - HW_REVID(1, 1, 1, 0, 1, 0, 0), - HasLWake, - }, - - { "RTL-8100", - HW_REVID(1, 1, 1, 1, 0, 1, 0), - HasLWake, - }, - - { "RTL-8100B/8139D", - HW_REVID(1, 1, 1, 0, 1, 0, 1), - HasHltClk /* XXX undocumented? */ - | HasLWake, - }, - - { "RTL-8101", - HW_REVID(1, 1, 1, 0, 1, 1, 1), - HasLWake, - }, -}; - -struct rtl_extra_stats { - unsigned long early_rx; - unsigned long tx_buf_mapped; - unsigned long tx_timeouts; - unsigned long rx_lost_in_ring; -}; - -struct rtl8139_private { - void __iomem *mmio_addr; - int drv_flags; - struct pci_dev *pci_dev; - u32 msg_enable; - struct napi_struct napi; - struct net_device *dev; - - unsigned char *rx_ring; - unsigned int cur_rx; /* RX buf index of next pkt */ - dma_addr_t rx_ring_dma; - - unsigned int tx_flag; - unsigned long cur_tx; - unsigned long dirty_tx; - unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ - unsigned char *tx_bufs; /* Tx bounce buffer region. */ - dma_addr_t tx_bufs_dma; - - signed char phys[4]; /* MII device addresses. */ - - /* Twister tune state. */ - char twistie, twist_row, twist_col; - - unsigned int watchdog_fired : 1; - unsigned int default_port : 4; /* Last dev->if_port value. */ - unsigned int have_thread : 1; - - spinlock_t lock; - spinlock_t rx_lock; - - chip_t chipset; - u32 rx_config; - struct rtl_extra_stats xstats; - - struct delayed_work thread; - - struct mii_if_info mii; - unsigned int regs_len; - unsigned long fifo_copy_timeout; -}; - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(use_io, int, 0); -MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO"); -module_param(multicast_filter_limit, int, 0); -module_param_array(media, int, NULL, 0); -module_param_array(full_duplex, int, NULL, 0); -module_param(debug, int, 0); -MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); -MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); -MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); - -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); -static int rtl8139_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void rtl8139_start_thread(struct rtl8139_private *tp); -static void rtl8139_tx_timeout (struct net_device *dev); -static void rtl8139_init_ring (struct net_device *dev); -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8139_poll_controller(struct net_device *dev); -#endif -static int rtl8139_set_mac_address(struct net_device *dev, void *p); -static int rtl8139_poll(struct napi_struct *napi, int budget); -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); -static int rtl8139_close (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static void rtl8139_set_rx_mode (struct net_device *dev); -static void __set_rx_mode (struct net_device *dev); -static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (struct work_struct *work); -static void rtl8139_tx_timeout_task(struct work_struct *work); -static const struct ethtool_ops rtl8139_ethtool_ops; - -/* write MMIO register, with flush */ -/* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) - -/* write MMIO register */ -#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) - -/* read MMIO register */ -#define RTL_R8(reg) ioread8 (ioaddr + (reg)) -#define RTL_R16(reg) ioread16 (ioaddr + (reg)) -#define RTL_R32(reg) ioread32 (ioaddr + (reg)) - - -static const u16 rtl8139_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | - TxErr | TxOK | RxErr | RxOK; - -static const u16 rtl8139_norx_intr_mask = - PCIErr | PCSTimeout | RxUnderrun | - TxErr | TxOK | RxErr ; - -#if RX_BUF_IDX == 0 -static const unsigned int rtl8139_rx_config = - RxCfgRcv8K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 1 -static const unsigned int rtl8139_rx_config = - RxCfgRcv16K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 2 -static const unsigned int rtl8139_rx_config = - RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#elif RX_BUF_IDX == 3 -static const unsigned int rtl8139_rx_config = - RxCfgRcv64K | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); -#else -#error "Invalid configuration for 8139_RXBUF_IDX" -#endif - -static const unsigned int rtl8139_tx_config = - TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); - -static void __rtl8139_cleanup_dev (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - struct pci_dev *pdev; - - assert (dev != NULL); - assert (tp->pci_dev != NULL); - pdev = tp->pci_dev; - - if (tp->mmio_addr) - pci_iounmap (pdev, tp->mmio_addr); - - /* it's ok to call this even if we have no regions to free */ - pci_release_regions (pdev); - - free_netdev(dev); - pci_set_drvdata (pdev, NULL); -} - - -static void rtl8139_chip_reset (void __iomem *ioaddr) -{ - int i; - - /* Soft reset the chip. */ - RTL_W8 (ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - barrier(); - if ((RTL_R8 (ChipCmd) & CmdReset) == 0) - break; - udelay (10); - } -} - - -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8139_private *tp; - u8 tmp8; - int rc, disable_dev_on_err = 0; - unsigned int i; - unsigned long pio_start, pio_end, pio_flags, pio_len; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 version; - - assert (pdev != NULL); - - /* dev and priv zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); - return ERR_PTR(-ENOMEM); - } - SET_NETDEV_DEV(dev, &pdev->dev); - - tp = netdev_priv(dev); - tp->pci_dev = pdev; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device (pdev); - if (rc) - goto err_out; - - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); - - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); - - /* set this immediately, we need to know before - * we talk to the chip directly */ - pr_debug("PIO region size == 0x%02lX\n", pio_len); - pr_debug("MMIO region size == 0x%02lX\n", mmio_len); - -retry: - if (use_io) { - /* make sure PCI base addr 0 is PIO */ - if (!(pio_flags & IORESOURCE_IO)) { - dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - /* check for weird/broken PCI region reporting */ - if (pio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } else { - /* make sure PCI base addr 1 is MMIO */ - if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); - rc = -ENODEV; - goto err_out; - } - if (mmio_len < RTL_MIN_IO_SIZE) { - dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n"); - rc = -ENODEV; - goto err_out; - } - } - - rc = pci_request_regions (pdev, DRV_NAME); - if (rc) - goto err_out; - disable_dev_on_err = 1; - - /* enable PCI bus-mastering */ - pci_set_master (pdev); - - if (use_io) { - ioaddr = pci_iomap(pdev, 0, 0); - if (!ioaddr) { - dev_err(&pdev->dev, "cannot map PIO, aborting\n"); - rc = -EIO; - goto err_out; - } - dev->base_addr = pio_start; - tp->regs_len = pio_len; - } else { - /* ioremap MMIO region */ - ioaddr = pci_iomap(pdev, 1, 0); - if (ioaddr == NULL) { - dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n"); - pci_release_regions(pdev); - use_io = 1; - goto retry; - } - dev->base_addr = (long) ioaddr; - tp->regs_len = mmio_len; - } - tp->mmio_addr = ioaddr; - - /* Bring old chips out of low-power mode. */ - RTL_W8 (HltClk, 'R'); - - /* check for missing/broken hardware */ - if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { - dev_err(&pdev->dev, "Chip not responding, ignoring board\n"); - rc = -EIO; - goto err_out; - } - - /* identify chip attached to board */ - version = RTL_R32 (TxConfig) & HW_REVID_MASK; - for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (version == rtl_chip_info[i].version) { - tp->chipset = i; - goto match; - } - - /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - i = 0; - dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); - dev_dbg(&pdev->dev, "TxConfig = 0x%x\n", RTL_R32 (TxConfig)); - tp->chipset = 0; - -match: - pr_debug("chipset id (%d) == index %d, '%s'\n", - version, i, rtl_chip_info[i].name); - - if (tp->chipset >= CH_8139B) { - u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - pr_debug("PCI PM wakeup\n"); - if ((rtl_chip_info[tp->chipset].flags & HasLWake) && - (tmp8 & LWAKE)) - new_tmp8 &= ~LWAKE; - new_tmp8 |= Cfg1_PM_Enable; - if (new_tmp8 != tmp8) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tmp8); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config4, tmp8 & ~LWPTN); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } - } - } else { - pr_debug("Old chip wakeup\n"); - tmp8 = RTL_R8 (Config1); - tmp8 &= ~(SLEEP | PWRDN); - RTL_W8 (Config1, tmp8); - } - - rtl8139_chip_reset (ioaddr); - - return dev; - -err_out: - __rtl8139_cleanup_dev (dev); - if (disable_dev_on_err) - pci_disable_device (pdev); - return ERR_PTR(rc); -} - -static const struct net_device_ops rtl8139_netdev_ops = { - .ndo_open = rtl8139_open, - .ndo_stop = rtl8139_close, - .ndo_get_stats = rtl8139_get_stats, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = rtl8139_set_mac_address, - .ndo_start_xmit = rtl8139_start_xmit, - .ndo_set_multicast_list = rtl8139_set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = rtl8139_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8139_poll_controller, -#endif -}; - -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8139_private *tp; - int i, addr_len, option; - void __iomem *ioaddr; - static int board_idx = -1; - - assert (pdev != NULL); - assert (ent != NULL); - - board_idx++; - - /* when we're built into the kernel, the driver version message - * is only printed if at least one 8139 board has been found - */ -#ifndef MODULE - { - static int printed_version; - if (!printed_version++) - pr_info(RTL8139_DRIVER_NAME "\n"); - } -#endif - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { - dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n", - pdev->vendor, pdev->device, pdev->revision); - return -ENODEV; - } - - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && - pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("OQO Model 2 detected. Forcing PIO\n"); - use_io = 1; - } - - dev = rtl8139_init_board (pdev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - assert (dev != NULL); - tp = netdev_priv(dev); - tp->dev = dev; - - ioaddr = tp->mmio_addr; - assert (ioaddr != NULL); - - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - ((__le16 *) (dev->dev_addr))[i] = - cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* The Rtl8139-specific entries in the device structure. */ - dev->netdev_ops = &rtl8139_netdev_ops; - dev->ethtool_ops = &rtl8139_ethtool_ops; - dev->watchdog_timeo = TX_TIMEOUT; - netif_napi_add(dev, &tp->napi, rtl8139_poll, 64); - - /* note: the hardware is not capable of sg/csum/highdma, however - * through the use of skb_copy_and_csum_dev we enable these - * features - */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->irq = pdev->irq; - - /* tp zeroed and aligned in alloc_etherdev */ - tp = netdev_priv(dev); - - /* note: tp->chipset set in rtl8139_init_board */ - tp->drv_flags = board_info[ent->driver_data].hw_flags; - tp->mmio_addr = ioaddr; - tp->msg_enable = - (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); - spin_lock_init (&tp->lock); - spin_lock_init (&tp->rx_lock); - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - tp->mii.dev = dev; - tp->mii.mdio_read = mdio_read; - tp->mii.mdio_write = mdio_write; - tp->mii.phy_id_mask = 0x3f; - tp->mii.reg_num_mask = 0x1f; - - /* dev is fully set up and ready to use now */ - pr_debug("about to register device named %s (%p)...\n", - dev->name, dev); - i = register_netdev (dev); - if (i) goto err_out; - - pci_set_drvdata (pdev, dev); - - netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n", - board_info[ent->driver_data].name, - dev->base_addr, dev->dev_addr, dev->irq); - - netdev_dbg(dev, "Identified 8139 chip type '%s'\n", - rtl_chip_info[tp->chipset].name); - - /* Find the connected MII xcvrs. - Doing this in open() would allow detecting external xcvrs later, but - takes too much time. */ -#ifdef CONFIG_8139TOO_8129 - if (tp->drv_flags & HAS_MII_XCVR) { - int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - u16 advertising = mdio_read(dev, phy, 4); - tp->phys[phy_idx++] = phy; - netdev_info(dev, "MII transceiver %d status 0x%04x advertising %04x\n", - phy, mii_status, advertising); - } - } - if (phy_idx == 0) { - netdev_info(dev, "No MII transceivers found! Assuming SYM transceiver\n"); - tp->phys[0] = 32; - } - } else -#endif - tp->phys[0] = 32; - tp->mii.phy_id = tp->phys[0]; - - /* The lower four bits are the media type. */ - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - if (option > 0) { - tp->mii.full_duplex = (option & 0x210) ? 1 : 0; - tp->default_port = option & 0xFF; - if (tp->default_port) - tp->mii.force_media = 1; - } - if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) - tp->mii.full_duplex = full_duplex[board_idx]; - if (tp->mii.full_duplex) { - netdev_info(dev, "Media type forced to Full Duplex\n"); - /* Changing the MII-advertised media because might prevent - re-connection. */ - tp->mii.force_media = 1; - } - if (tp->default_port) { - netdev_info(dev, " Forcing %dMbps %s-duplex operation\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); - mdio_write(dev, tp->phys[0], 0, - ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ - ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ - } - - /* Put the chip into low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; - -err_out: - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); - return i; -} - - -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - assert (dev != NULL); - - flush_scheduled_work(); - - unregister_netdev (dev); - - __rtl8139_cleanup_dev (dev); - pci_disable_device (pdev); -} - - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ - -#define eeprom_delay() (void)RTL_R32(Cfg9346) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (EE_READ_CMD << addr_len); - - RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - RTL_W8 (Cfg9346, EE_ENB | dataval); - eeprom_delay (); - RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); - eeprom_delay (); - } - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - - for (i = 16; i > 0; i--) { - RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); - eeprom_delay (); - retval = - (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : - 0); - RTL_W8 (Cfg9346, EE_ENB); - eeprom_delay (); - } - - /* Terminate the EEPROM access. */ - RTL_W8 (Cfg9346, ~EE_CS); - eeprom_delay (); - - return retval; -} - -/* MII serial management: mostly bogus for now. */ -/* Read and write the MII management registers using software-generated - serial MDIO protocol. - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back PCI I/O cycles, but we insert a delay to avoid - "overclocking" issues. */ -#define MDIO_DIR 0x80 -#define MDIO_DATA_OUT 0x04 -#define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) - -#define mdio_delay() RTL_R8(Config4) - - -static const char mii_2_8139_map[8] = { - BasicModeCtrl, - BasicModeStatus, - 0, - 0, - NWayAdvert, - NWayLPAR, - NWayExpansion, - 0 -}; - - -#ifdef CONFIG_8139TOO_8129 -/* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void __iomem *ioaddr) -{ - int i; - - for (i = 32; i >= 0; i--) { - RTL_W8 (Config4, MDIO_WRITE1); - mdio_delay (); - RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); - mdio_delay (); - } -} -#endif - -static int mdio_read (struct net_device *dev, int phy_id, int location) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval = 0; -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - return location < 8 && mii_2_8139_map[location] ? - RTL_R16 (mii_2_8139_map[location]) : 0; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - - RTL_W8 (Config4, MDIO_DIR | dataval); - mdio_delay (); - RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); - mdio_delay (); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif - - return (retval >> 1) & 0xffff; -} - - -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) -{ - struct rtl8139_private *tp = netdev_priv(dev); -#ifdef CONFIG_8139TOO_8129 - void __iomem *ioaddr = tp->mmio_addr; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; -#endif - - if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void __iomem *ioaddr = tp->mmio_addr; - if (location == 0) { - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W16 (BasicModeCtrl, value); - RTL_W8 (Cfg9346, Cfg9346_Lock); - } else if (location < 8 && mii_2_8139_map[location]) - RTL_W16 (mii_2_8139_map[location], value); - return; - } - -#ifdef CONFIG_8139TOO_8129 - mdio_sync (ioaddr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - RTL_W8 (Config4, dataval); - mdio_delay (); - RTL_W8 (Config4, dataval | MDIO_CLK); - mdio_delay (); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - RTL_W8 (Config4, 0); - mdio_delay (); - RTL_W8 (Config4, MDIO_CLK); - mdio_delay (); - } -#endif -} - - -static int rtl8139_open (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int retval; - void __iomem *ioaddr = tp->mmio_addr; - - retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) - return retval; - - tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - &tp->tx_bufs_dma, GFP_KERNEL); - tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - &tp->rx_ring_dma, GFP_KERNEL); - if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { - free_irq(dev->irq, dev); - - if (tp->tx_bufs) - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - if (tp->rx_ring) - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - - return -ENOMEM; - - } - - napi_enable(&tp->napi); - - tp->mii.full_duplex = tp->mii.force_media; - tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_start_queue (dev); - - netif_dbg(tp, ifup, dev, - "%s() ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n", - __func__, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); - - rtl8139_start_thread(tp); - - return 0; -} - - -static void rtl_check_media (struct net_device *dev, unsigned int init_media) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - if (tp->phys[0] >= 0) { - mii_check_media(&tp->mii, netif_msg_link(tp), init_media); - } -} - -/* Start the hardware at open or resume. */ -static void rtl8139_hw_start (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 i; - u8 tmp; - - /* Bring old chips out of low-power mode. */ - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'R'); - - rtl8139_chip_reset (ioaddr); - - /* unlock Config[01234] and BMCR register writes */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Restore our idea of the MAC address. */ - RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4))); - - tp->cur_rx = 0; - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - RTL_W32 (TxConfig, rtl8139_tx_config); - - rtl_check_media (dev, 1); - - if (tp->chipset >= CH_8139B) { - /* Disable magic packet scanning, which is enabled - * when PM is enabled in Config1. It can be reenabled - * via ETHTOOL_SWOL if desired. */ - RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); - } - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Tx buffer DMA addresses */ - for (i = 0; i < NUM_TX_DESC; i++) - RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - - RTL_W32 (RxMissed, 0); - - rtl8139_set_rx_mode (dev); - - /* no early-rx interrupts */ - RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear); - - /* make sure RxTx has started */ - tmp = RTL_R8 (ChipCmd); - if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16 (IntrMask, rtl8139_intr_mask); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void rtl8139_init_ring (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int i; - - tp->cur_rx = 0; - tp->cur_tx = 0; - tp->dirty_tx = 0; - - for (i = 0; i < NUM_TX_DESC; i++) - tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; -} - - -/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ -static int next_tick = 3 * HZ; - -#ifndef CONFIG_8139TOO_TUNE_TWISTER -static inline void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) {} -#else -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -static void rtl8139_tune_twister (struct net_device *dev, - struct rtl8139_private *tp) -{ - int linkcase; - void __iomem *ioaddr = tp->mmio_addr; - - /* This is a complicated state machine to configure the "twister" for - impedance/echos based on the cable length. - All of this is magic and undocumented. - */ - switch (tp->twistie) { - case 1: - if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { - /* We have link beat, let us tune the twister. */ - RTL_W16 (CSCR, CSCR_LinkDownOffCmd); - tp->twistie = 2; /* Change to state 2. */ - next_tick = HZ / 10; - } else { - /* Just put in some reasonable defaults for when beat returns. */ - RTL_W16 (CSCR, CSCR_LinkDownCmd); - RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - tp->twistie = 0; /* Bail from future actions. */ - } - break; - case 2: - /* Read how long it took to hear the echo. */ - linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; - if (linkcase == 0x7000) - tp->twist_row = 3; - else if (linkcase == 0x3000) - tp->twist_row = 2; - else if (linkcase == 0x1000) - tp->twist_row = 1; - else - tp->twist_row = 0; - tp->twist_col = 0; - tp->twistie = 3; /* Change to state 2. */ - next_tick = HZ / 10; - break; - case 3: - /* Put out four tuning parameters, one per 100msec. */ - if (tp->twist_col == 0) - RTL_W16 (FIFOTMS, 0); - RTL_W32 (PARA7c, param[(int) tp->twist_row] - [(int) tp->twist_col]); - next_tick = HZ / 10; - if (++tp->twist_col >= 4) { - /* For short cables we are done. - For long cables (row == 3) check for mistune. */ - tp->twistie = - (tp->twist_row == 3) ? 4 : 0; - } - break; - case 4: - /* Special case for long cables: check for mistune. */ - if ((RTL_R16 (CSCR) & - CSCR_LinkStatusBits) == 0x7000) { - tp->twistie = 0; - break; - } else { - RTL_W32 (PARA7c, 0xfb38de03); - tp->twistie = 5; - next_tick = HZ / 10; - } - break; - case 5: - /* Retune for shorter cable (column 2). */ - RTL_W32 (FIFOTMS, 0x20); - RTL_W32 (PARA78, PARA78_default); - RTL_W32 (PARA7c, PARA7c_default); - RTL_W32 (FIFOTMS, 0x00); - tp->twist_row = 2; - tp->twist_col = 0; - tp->twistie = 3; - next_tick = HZ / 10; - break; - - default: - /* do nothing */ - break; - } -} -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - -static inline void rtl8139_thread_iter (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - int mii_lpa; - - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); - - if (!tp->mii.force_media && mii_lpa != 0xffff) { - int duplex = ((mii_lpa & LPA_100FULL) || - (mii_lpa & 0x01C0) == 0x0040); - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; - - if (mii_lpa) { - netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n", - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - } else { - netdev_info(dev, "media is unconnected, link down, or incompatible connection\n"); - } -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } - } - - next_tick = HZ * 60; - - rtl8139_tune_twister (dev, tp); - - netdev_dbg(dev, "Media selection tick, Link partner %04x\n", - RTL_R16(NWayLPAR)); - netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x\n", - RTL_R16(IntrMask), RTL_R16(IntrStatus)); - netdev_dbg(dev, "Chip config %02x %02x\n", - RTL_R8(Config0), RTL_R8(Config1)); -} - -static void rtl8139_thread (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - unsigned long thr_delay = next_tick; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - if (tp->watchdog_fired) { - tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(work); - } else - rtl8139_thread_iter(dev, tp, tp->mmio_addr); - - if (tp->have_thread) - schedule_delayed_work(&tp->thread, thr_delay); -out_unlock: - rtnl_unlock (); -} - -static void rtl8139_start_thread(struct rtl8139_private *tp) -{ - tp->twistie = 0; - if (tp->chipset == CH_8139_K) - tp->twistie = 1; - else if (tp->drv_flags & HAS_LNK_CHNG) - return; - - tp->have_thread = 1; - tp->watchdog_fired = 0; - - schedule_delayed_work(&tp->thread, next_tick); -} - -static inline void rtl8139_tx_clear (struct rtl8139_private *tp) -{ - tp->cur_tx = 0; - tp->dirty_tx = 0; - - /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ -} - -static void rtl8139_tx_timeout_task (struct work_struct *work) -{ - struct rtl8139_private *tp = - container_of(work, struct rtl8139_private, thread.work); - struct net_device *dev = tp->mii.dev; - void __iomem *ioaddr = tp->mmio_addr; - int i; - u8 tmp8; - - netdev_dbg(dev, "Transmit timeout, status %02x %04x %04x media %02x\n", - RTL_R8(ChipCmd), RTL_R16(IntrStatus), - RTL_R16(IntrMask), RTL_R8(MediaStatus)); - /* Emit info to figure out what went wrong. */ - netdev_dbg(dev, "Tx queue start entry %ld dirty entry %ld\n", - tp->cur_tx, tp->dirty_tx); - for (i = 0; i < NUM_TX_DESC; i++) - netdev_dbg(dev, "Tx descriptor %d is %08x%s\n", - i, RTL_R32(TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); - - tp->xstats.tx_timeouts++; - - /* disable Tx ASAP, if not already */ - tmp8 = RTL_R8 (ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8 (ChipCmd, CmdRxEnb); - - spin_lock_bh(&tp->rx_lock); - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0x0000); - - /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8139_tx_clear (tp); - spin_unlock_irq(&tp->lock); - - /* ...and finally, reset everything */ - if (netif_running(dev)) { - rtl8139_hw_start (dev); - netif_wake_queue (dev); - } - spin_unlock_bh(&tp->rx_lock); -} - -static void rtl8139_tx_timeout (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - tp->watchdog_fired = 1; - if (!tp->have_thread) { - INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); - schedule_delayed_work(&tp->thread, next_tick); - } -} - -static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int entry; - unsigned int len = skb->len; - unsigned long flags; - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % NUM_TX_DESC; - - /* Note: the chip doesn't have auto-pad! */ - if (likely(len < TX_BUF_SIZE)) { - if (len < ETH_ZLEN) - memset(tp->tx_buf[entry], 0, ETH_ZLEN); - skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - spin_lock_irqsave(&tp->lock, flags); - /* - * Writing to TxStatus triggers a DMA transfer of the data - * copied to tp->tx_buf[entry] above. Use a memory barrier - * to make sure that the device sees the updated data. - */ - wmb(); - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - tp->cur_tx++; - - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) - netif_stop_queue (dev); - spin_unlock_irqrestore(&tp->lock, flags); - - netif_dbg(tp, tx_queued, dev, "Queued Tx packet size %u to slot %d\n", - len, entry); - - return NETDEV_TX_OK; -} - - -static void rtl8139_tx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert (dev != NULL); - assert (ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - int txstatus; - - txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32))); - - if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) - break; /* It still hasn't been Txed */ - - /* Note: TxCarrierLost is always asserted at 100mbps. */ - if (txstatus & (TxOutOfWindow | TxAborted)) { - /* There was an major error, log it. */ - netif_dbg(tp, tx_err, dev, "Transmit error, Tx status %08x\n", - txstatus); - dev->stats.tx_errors++; - if (txstatus & TxAborted) { - dev->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt); - RTL_W16 (IntrStatus, TxErr); - wmb(); - } - if (txstatus & TxCarrierLost) - dev->stats.tx_carrier_errors++; - if (txstatus & TxOutOfWindow) - dev->stats.tx_window_errors++; - } else { - if (txstatus & TxUnderrun) { - /* Add 64 to the Tx FIFO threshold. */ - if (tp->tx_flag < 0x00300000) - tp->tx_flag += 0x00020000; - dev->stats.tx_fifo_errors++; - } - dev->stats.collisions += (txstatus >> 24) & 15; - dev->stats.tx_bytes += txstatus & 0x7ff; - dev->stats.tx_packets++; - } - - dirty_tx++; - tx_left--; - } - -#ifndef RTL8139_NDEBUG - if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - netdev_err(dev, "Out-of-sync dirty pointer, %ld vs. %ld\n", - dirty_tx, tp->cur_tx); - dirty_tx += NUM_TX_DESC; - } -#endif /* RTL8139_NDEBUG */ - - /* only wake the queue if we did work, and the queue is stopped */ - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - mb(); - netif_wake_queue (dev); - } -} - - -/* TODO: clean this up! Rx reset need not be this intensive */ -static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void __iomem *ioaddr) -{ - u8 tmp8; -#ifdef CONFIG_8139_OLD_RX_RESET - int tmp_work; -#endif - - netif_dbg(tp, rx_err, dev, "Ethernet frame had errors, status %08x\n", - rx_status); - dev->stats.rx_errors++; - if (!(rx_status & RxStatusOK)) { - if (rx_status & RxTooLong) { - netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n", - rx_status); - /* A.C.: The chip hangs here. */ - } - if (rx_status & (RxBadSymbol | RxBadAlign)) - dev->stats.rx_frame_errors++; - if (rx_status & (RxRunt | RxTooLong)) - dev->stats.rx_length_errors++; - if (rx_status & RxCRCErr) - dev->stats.rx_crc_errors++; - } else { - tp->xstats.rx_lost_in_ring++; - } - -#ifndef CONFIG_8139_OLD_RX_RESET - tmp8 = RTL_R8 (ChipCmd); - RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb); - RTL_W8 (ChipCmd, tmp8); - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; -#else - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ - - /* disable receive */ - RTL_W8_F (ChipCmd, CmdTxEnb); - tmp_work = 200; - while (--tmp_work > 0) { - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if (!(tmp8 & CmdRxEnb)) - break; - } - if (tmp_work <= 0) - netdev_warn(dev, "rx stop wait too long\n"); - /* restart receive */ - tmp_work = 200; - while (--tmp_work > 0) { - RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb); - udelay(1); - tmp8 = RTL_R8 (ChipCmd); - if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) - break; - } - if (tmp_work <= 0) - netdev_warn(dev, "tx/rx enable wait too long\n"); - - /* and reinitialize all rx related registers */ - RTL_W8_F (Cfg9346, Cfg9346_Unlock); - /* Must enable Tx/Rx before setting transfer thresholds! */ - RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - - tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, tp->rx_config); - tp->cur_rx = 0; - - netdev_dbg(dev, "init buffer addresses\n"); - - /* Lock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Lock); - - /* init Rx ring buffer DMA address */ - RTL_W32_F (RxBuf, tp->rx_ring_dma); - - /* A.C.: Reset the multicast list. */ - __set_rx_mode (dev); -#endif -} - -#if RX_BUF_IDX == 3 -static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring, - u32 offset, unsigned int size) -{ - u32 left = RX_BUF_LEN - offset; - - if (size > left) { - skb_copy_to_linear_data(skb, ring + offset, left); - skb_copy_to_linear_data_offset(skb, left, ring, size - left); - } else - skb_copy_to_linear_data(skb, ring + offset, size); -} -#endif - -static void rtl8139_isr_ack(struct rtl8139_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u16 status; - - status = RTL_R16 (IntrStatus) & RxAckBits; - - /* Clear out errors and receive interrupts */ - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->dev->stats.rx_errors++; - if (status & RxFIFOOver) - tp->dev->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } -} - -static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, - int budget) -{ - void __iomem *ioaddr = tp->mmio_addr; - int received = 0; - unsigned char *rx_ring = tp->rx_ring; - unsigned int cur_rx = tp->cur_rx; - unsigned int rx_size = 0; - - netdev_dbg(dev, "In %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", - __func__, (u16)cur_rx, - RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); - - while (netif_running(dev) && received < budget && - (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { - u32 ring_offset = cur_rx % RX_BUF_LEN; - u32 rx_status; - unsigned int pkt_size; - struct sk_buff *skb; - - rmb(); - - /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset)); - rx_size = rx_status >> 16; - pkt_size = rx_size - 4; - - netif_dbg(tp, rx_status, dev, "%s() status %04x, size %04x, cur %04x\n", - __func__, rx_status, rx_size, cur_rx); -#if RTL8139_DEBUG > 2 - print_hex_dump(KERN_DEBUG, "Frame contents: ", - DUMP_PREFIX_OFFSET, 16, 1, - &rx_ring[ring_offset], 70, true); -#endif - - /* Packet copy from FIFO still in progress. - * Theoretically, this should never happen - * since EarlyRx is disabled. - */ - if (unlikely(rx_size == 0xfff0)) { - if (!tp->fifo_copy_timeout) - tp->fifo_copy_timeout = jiffies + 2; - else if (time_after(jiffies, tp->fifo_copy_timeout)) { - netdev_dbg(dev, "hung FIFO. Reset\n"); - rx_size = 0; - goto no_early_rx; - } - netif_dbg(tp, intr, dev, "fifo copy in progress\n"); - tp->xstats.early_rx++; - break; - } - -no_early_rx: - tp->fifo_copy_timeout = 0; - - /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), - * Rx process gets reset, so we abort any further - * Rx processing. - */ - if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || - (rx_size < 8) || - (!(rx_status & RxStatusOK)))) { - rtl8139_rx_err (rx_status, dev, tp, ioaddr); - received = -1; - goto out; - } - - /* Malloc up new buffer, compatible with net-2e. */ - /* Omit the four octet CRC from the length. */ - - skb = netdev_alloc_skb_ip_align(dev, pkt_size); - if (likely(skb)) { -#if RX_BUF_IDX == 3 - wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); -#else - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); -#endif - skb_put (skb, pkt_size); - - skb->protocol = eth_type_trans (skb, dev); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - - netif_receive_skb (skb); - } else { - if (net_ratelimit()) - netdev_warn(dev, "Memory squeeze, dropping packet\n"); - dev->stats.rx_dropped++; - } - received++; - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - - rtl8139_isr_ack(tp); - } - - if (unlikely(!received || rx_size == 0xfff0)) - rtl8139_isr_ack(tp); - - netdev_dbg(dev, "Done %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", - __func__, cur_rx, - RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); - - tp->cur_rx = cur_rx; - - /* - * The receive buffer should be mostly empty. - * Tell NAPI to reenable the Rx irq. - */ - if (tp->fifo_copy_timeout) - received = budget; - -out: - return received; -} - - -static void rtl8139_weird_interrupt (struct net_device *dev, - struct rtl8139_private *tp, - void __iomem *ioaddr, - int status, int link_changed) -{ - netdev_dbg(dev, "Abnormal interrupt, status %08x\n", status); - - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); - - /* Update the error count. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - if ((status & RxUnderrun) && link_changed && - (tp->drv_flags & HAS_LNK_CHNG)) { - rtl_check_media(dev, 0); - status &= ~RxUnderrun; - } - - if (status & (RxUnderrun | RxErr)) - dev->stats.rx_errors++; - - if (status & PCSTimeout) - dev->stats.rx_length_errors++; - if (status & RxUnderrun) - dev->stats.rx_fifo_errors++; - if (status & PCIErr) { - u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); - pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - - netdev_err(dev, "PCI Bus error %04x\n", pci_cmd_status); - } -} - -static int rtl8139_poll(struct napi_struct *napi, int budget) -{ - struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - spin_lock(&tp->rx_lock); - work_done = 0; - if (likely(RTL_R16(IntrStatus) & RxAckBits)) - work_done += rtl8139_rx(dev, tp, budget); - - if (work_done < budget) { - unsigned long flags; - /* - * Order is important since data can get interrupted - * again when we think we are done. - */ - spin_lock_irqsave(&tp->lock, flags); - __napi_complete(napi); - RTL_W16_F(IntrMask, rtl8139_intr_mask); - spin_unlock_irqrestore(&tp->lock, flags); - } - spin_unlock(&tp->rx_lock); - - return work_done; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u16 status, ackstat; - int link_changed = 0; /* avoid bogus "uninit" warning */ - int handled = 0; - - spin_lock (&tp->lock); - status = RTL_R16 (IntrStatus); - - /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) - goto out; - - handled = 1; - - /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) - goto out; - - /* close possible race's with dev_close */ - if (unlikely(!netif_running(dev))) { - RTL_W16 (IntrMask, 0); - goto out; - } - - /* Acknowledge all of the current interrupt sources ASAP, but - an first get an additional status bit from CSCR. */ - if (unlikely(status & RxUnderrun)) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - - ackstat = status & ~(RxAckBits | TxErr); - if (ackstat) - RTL_W16 (IntrStatus, ackstat); - - /* Receive packets are processed by poll routine. - If not running start it now. */ - if (status & RxAckBits){ - if (napi_schedule_prep(&tp->napi)) { - RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __napi_schedule(&tp->napi); - } - } - - /* Check uncommon events with one test. */ - if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) - rtl8139_weird_interrupt (dev, tp, ioaddr, - status, link_changed); - - if (status & (TxOK | TxErr)) { - rtl8139_tx_interrupt (dev, tp, ioaddr); - if (status & TxErr) - RTL_W16 (IntrStatus, TxErr); - } - out: - spin_unlock (&tp->lock); - - netdev_dbg(dev, "exiting interrupt, intr_status=%#4.4x\n", - RTL_R16(IntrStatus)); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - */ -static void rtl8139_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - rtl8139_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static int rtl8139_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - spin_lock_irq(&tp->lock); - - RTL_W8_F(Cfg9346, Cfg9346_Unlock); - RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); - RTL_W8_F(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static int rtl8139_close (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - netif_stop_queue(dev); - napi_disable(&tp->napi); - - netif_dbg(tp, ifdown, dev, "Shutting down ethercard, status was 0x%04x\n", - RTL_R16(IntrStatus)); - - spin_lock_irqsave (&tp->lock, flags); - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8 (ChipCmd, 0); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16 (IntrMask, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - free_irq (dev->irq, dev); - - rtl8139_tx_clear (tp); - - dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN, - tp->rx_ring, tp->rx_ring_dma); - dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN, - tp->tx_bufs, tp->tx_bufs_dma); - tp->rx_ring = NULL; - tp->tx_bufs = NULL; - - /* Green! Put the chip in low-power mode. */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); - - if (rtl_chip_info[tp->chipset].flags & HasHltClk) - RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - - return 0; -} - - -/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to - kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and - other threads or interrupts aren't messing with the 8139. */ -static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - spin_lock_irq(&tp->lock); - if (rtl_chip_info[tp->chipset].flags & HasLWake) { - u8 cfg3 = RTL_R8 (Config3); - u8 cfg5 = RTL_R8 (Config5); - - wol->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - - wol->wolopts = 0; - if (cfg3 & Cfg3_LinkUp) - wol->wolopts |= WAKE_PHY; - if (cfg3 & Cfg3_Magic) - wol->wolopts |= WAKE_MAGIC; - /* (KON)FIXME: See how netdev_set_wol() handles the - following constants. */ - if (cfg5 & Cfg5_UWF) - wol->wolopts |= WAKE_UCAST; - if (cfg5 & Cfg5_MWF) - wol->wolopts |= WAKE_MCAST; - if (cfg5 & Cfg5_BWF) - wol->wolopts |= WAKE_BCAST; - } - spin_unlock_irq(&tp->lock); -} - - -/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes - that wol points to kernel memory and other threads or interrupts - aren't messing with the 8139. */ -static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 support; - u8 cfg3, cfg5; - - support = ((rtl_chip_info[tp->chipset].flags & HasLWake) - ? (WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) - : 0); - if (wol->wolopts & ~support) - return -EINVAL; - - spin_lock_irq(&tp->lock); - cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); - if (wol->wolopts & WAKE_PHY) - cfg3 |= Cfg3_LinkUp; - if (wol->wolopts & WAKE_MAGIC) - cfg3 |= Cfg3_Magic; - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config3, cfg3); - RTL_W8 (Cfg9346, Cfg9346_Lock); - - cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); - /* (KON)FIXME: These are untested. We may have to set the - CRC0, Wakeup0 and LSBCRC0 registers too, but I have no - documentation. */ - if (wol->wolopts & WAKE_UCAST) - cfg5 |= Cfg5_UWF; - if (wol->wolopts & WAKE_MCAST) - cfg5 |= Cfg5_MWF; - if (wol->wolopts & WAKE_BCAST) - cfg5 |= Cfg5_BWF; - RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct rtl8139_private *tp = netdev_priv(dev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = tp->regs_len; -} - -static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - mii_ethtool_gset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return 0; -} - -static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - spin_lock_irq(&tp->lock); - rc = mii_ethtool_sset(&tp->mii, cmd); - spin_unlock_irq(&tp->lock); - return rc; -} - -static int rtl8139_nway_reset(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_nway_restart(&tp->mii); -} - -static u32 rtl8139_get_link(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return mii_link_ok(&tp->mii); -} - -static u32 rtl8139_get_msglevel(struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - return tp->msg_enable; -} - -static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) -{ - struct rtl8139_private *tp = netdev_priv(dev); - tp->msg_enable = datum; -} - -static int rtl8139_get_regs_len(struct net_device *dev) -{ - struct rtl8139_private *tp; - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return 0; - tp = netdev_priv(dev); - return tp->regs_len; -} - -static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - struct rtl8139_private *tp; - - /* TODO: we are too slack to do reg dumping for pio, for now */ - if (use_io) - return; - tp = netdev_priv(dev); - - regs->version = RTL_REGS_VER; - - spin_lock_irq(&tp->lock); - memcpy_fromio(regbuf, tp->mmio_addr, regs->len); - spin_unlock_irq(&tp->lock); -} - -static int rtl8139_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return RTL_NUM_STATS; - default: - return -EOPNOTSUPP; - } -} - -static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) -{ - struct rtl8139_private *tp = netdev_priv(dev); - - data[0] = tp->xstats.early_rx; - data[1] = tp->xstats.tx_buf_mapped; - data[2] = tp->xstats.tx_timeouts; - data[3] = tp->xstats.rx_lost_in_ring; -} - -static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); -} - -static const struct ethtool_ops rtl8139_ethtool_ops = { - .get_drvinfo = rtl8139_get_drvinfo, - .get_settings = rtl8139_get_settings, - .set_settings = rtl8139_set_settings, - .get_regs_len = rtl8139_get_regs_len, - .get_regs = rtl8139_get_regs, - .nway_reset = rtl8139_nway_reset, - .get_link = rtl8139_get_link, - .get_msglevel = rtl8139_get_msglevel, - .set_msglevel = rtl8139_set_msglevel, - .get_wol = rtl8139_get_wol, - .set_wol = rtl8139_set_wol, - .get_strings = rtl8139_get_strings, - .get_sset_count = rtl8139_get_sset_count, - .get_ethtool_stats = rtl8139_get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct rtl8139_private *tp = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&tp->lock); - - return rc; -} - - -static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave (&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); - } - - return &dev->stats; -} - -/* Set or clear the multicast filter for this adaptor. - This routine is not state sensitive and need not be SMP locked. */ - -static void __set_rx_mode (struct net_device *dev) -{ - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp; - - netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08x\n", - dev->flags, RTL_R32(RxConfig)); - - /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - /* We can safely update without stopping the chip. */ - tmp = rtl8139_rx_config | rx_mode; - if (tp->rx_config != tmp) { - RTL_W32_F (RxConfig, tmp); - tp->rx_config = tmp; - } - RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32_F (MAR0 + 4, mc_filter[1]); -} - -static void rtl8139_set_rx_mode (struct net_device *dev) -{ - unsigned long flags; - struct rtl8139_private *tp = netdev_priv(dev); - - spin_lock_irqsave (&tp->lock, flags); - __set_rx_mode(dev); - spin_unlock_irqrestore (&tp->lock, flags); -} - -#ifdef CONFIG_PM - -static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - pci_save_state (pdev); - - if (!netif_running (dev)) - return 0; - - netif_device_detach (dev); - - spin_lock_irqsave (&tp->lock, flags); - - /* Disable interrupts, stop Tx and Rx. */ - RTL_W16 (IntrMask, 0); - RTL_W8 (ChipCmd, 0); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32 (RxMissed); - RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); - - pci_set_power_state (pdev, PCI_D3hot); - - return 0; -} - - -static int rtl8139_resume (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - pci_restore_state (pdev); - if (!netif_running (dev)) - return 0; - pci_set_power_state (pdev, PCI_D0); - rtl8139_init_ring (dev); - rtl8139_hw_start (dev); - netif_device_attach (dev); - return 0; -} - -#endif /* CONFIG_PM */ - - -static struct pci_driver rtl8139_pci_driver = { - .name = DRV_NAME, - .id_table = rtl8139_pci_tbl, - .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8139_suspend, - .resume = rtl8139_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init rtl8139_init_module (void) -{ - /* when we're a module, we always print a version message, - * even if no 8139 board is found. - */ -#ifdef MODULE - pr_info(RTL8139_DRIVER_NAME "\n"); -#endif - - return pci_register_driver(&rtl8139_pci_driver); -} - - -static void __exit rtl8139_cleanup_module (void) -{ - pci_unregister_driver (&rtl8139_pci_driver); -} - - -module_init(rtl8139_init_module); -module_exit(rtl8139_cleanup_module); diff --git a/devices/Makefile.am b/devices/Makefile.am index 238f060c..92ebf03f 100644 --- a/devices/Makefile.am +++ b/devices/Makefile.am @@ -38,44 +38,6 @@ SUBDIRS = \ # using HEADERS to enable tags target noinst_HEADERS = \ - 8139too-2.6.13-ethercat.c \ - 8139too-2.6.13-orig.c \ - 8139too-2.6.17-ethercat.c \ - 8139too-2.6.17-orig.c \ - 8139too-2.6.18-ethercat.c \ - 8139too-2.6.18-orig.c \ - 8139too-2.6.19-ethercat.c \ - 8139too-2.6.19-orig.c \ - 8139too-2.6.22-ethercat.c \ - 8139too-2.6.22-orig.c \ - 8139too-2.6.23-ethercat.c \ - 8139too-2.6.23-orig.c \ - 8139too-2.6.24-ethercat.c \ - 8139too-2.6.24-orig.c \ - 8139too-2.6.25-ethercat.c \ - 8139too-2.6.25-orig.c \ - 8139too-2.6.26-ethercat.c \ - 8139too-2.6.26-orig.c \ - 8139too-2.6.27-ethercat.c \ - 8139too-2.6.27-orig.c \ - 8139too-2.6.28-ethercat.c \ - 8139too-2.6.28-orig.c \ - 8139too-2.6.29-ethercat.c \ - 8139too-2.6.29-orig.c \ - 8139too-2.6.31-ethercat.c \ - 8139too-2.6.31-orig.c \ - 8139too-2.6.32-ethercat.c \ - 8139too-2.6.32-orig.c \ - 8139too-2.6.33-ethercat.c \ - 8139too-2.6.33-orig.c \ - 8139too-2.6.34-ethercat.c \ - 8139too-2.6.34-orig.c \ - 8139too-2.6.35-ethercat.c \ - 8139too-2.6.35-orig.c \ - 8139too-2.6.36-ethercat.c \ - 8139too-2.6.36-orig.c \ - 8139too-2.6.37-ethercat.c \ - 8139too-2.6.37-orig.c \ 8139too-3.0-ethercat.c \ 8139too-3.0-orig.c \ 8139too-3.10-ethercat.c \ @@ -102,28 +64,6 @@ noinst_HEADERS = \ 8139too-6.1-orig.c \ create_driver_table.py \ device_drivers_template.md \ - e100-2.6.20-ethercat.c \ - e100-2.6.20-orig.c \ - e100-2.6.24-ethercat.c \ - e100-2.6.24-orig.c \ - e100-2.6.26-ethercat.c \ - e100-2.6.26-orig.c \ - e100-2.6.27-ethercat.c \ - e100-2.6.27-orig.c \ - e100-2.6.28-ethercat.c \ - e100-2.6.28-orig.c \ - e100-2.6.29-ethercat.c \ - e100-2.6.29-orig.c \ - e100-2.6.31-ethercat.c \ - e100-2.6.31-orig.c \ - e100-2.6.32-ethercat.c \ - e100-2.6.32-orig.c \ - e100-2.6.33-ethercat.c \ - e100-2.6.33-orig.c \ - e100-2.6.35-ethercat.c \ - e100-2.6.35-orig.c \ - e100-2.6.37-ethercat.c \ - e100-2.6.37-orig.c \ e100-3.0-ethercat.c \ e100-3.0-orig.c \ e100-3.10-ethercat.c \ @@ -156,26 +96,6 @@ noinst_HEADERS = \ e100-6.4-orig.c \ ecdev.h \ generic.c \ - r8169-2.6.24-ethercat.c \ - r8169-2.6.24-orig.c \ - r8169-2.6.27-ethercat.c \ - r8169-2.6.27-orig.c \ - r8169-2.6.28-ethercat.c \ - r8169-2.6.28-orig.c \ - r8169-2.6.29-ethercat.c \ - r8169-2.6.29-orig.c \ - r8169-2.6.31-ethercat.c \ - r8169-2.6.31-orig.c \ - r8169-2.6.32-ethercat.c \ - r8169-2.6.32-orig.c \ - r8169-2.6.33-ethercat.c \ - r8169-2.6.33-orig.c \ - r8169-2.6.35-ethercat.c \ - r8169-2.6.35-orig.c \ - r8169-2.6.36-ethercat.c \ - r8169-2.6.36-orig.c \ - r8169-2.6.37-ethercat.c \ - r8169-2.6.37-orig.c \ r8169-3.10-ethercat.c \ r8169-3.10-orig.c \ r8169-3.12-ethercat.c \ diff --git a/devices/e100-2.6.20-ethercat.c b/devices/e100-2.6.20-ethercat.c deleted file mode 100644 index 634f0648..00000000 --- a/devices/e100-2.6.20-ethercat.c +++ /dev/null @@ -1,3052 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Recieve - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * senario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.17-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Florian Pose "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __FUNCTION__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - u16 status; - u16 command; - u32 link; - u32 rbd; - u16 actual_size; - u16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - u16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - u16 status; - u16 command; - u32 link; - union { - u8 iaaddr[ETH_ALEN]; - u32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - u32 buf_addr; - u16 size; - u16 eol; - } tbd; - } tcb; - u32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - u32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - u32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - u32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - u16 xmt_tco_frames, rcv_tco_frames; - u32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - u16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct net_device_stats net_stats; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u8 rev_id; - u16 leds; - u16 eeprom_wc; - u16 eeprom[256]; - spinlock_t mdio_lock; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)readb(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - writeb(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - writeb(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - writel(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - writel(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - writel(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - cpu_to_le16(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - writeb(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - writeb(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - writeb(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = readb(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - writeb(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return le16_to_cpu(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += cpu_to_le16(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - checksum = le16_to_cpu(0xBABA - checksum); - if(checksum != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += cpu_to_le16(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = le16_to_cpu(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!readb(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - writel(dma_addr, &nic->csr->scb.gen_ptr); - writeb(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (readl(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id); - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557*/ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = cpu_to_le16(cb_el); - nic->blank_rfd.rbd = 0xFFFFFFFF; - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if(nic->mac >= mac_82559_D101M) - config->tno_intr = 0x1; /* TCO stats enable */ - else - config->standard_stat_counter = 0x0; - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w rev_id */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interupts, something could have been set */ - writeb(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device_stats *ns = &nic->net_stats; - struct stats *s = &nic->mem->stats; - u32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (u32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so where always waiting for results of the - * previous command. */ - - if(*complete == le32_to_cpu(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - } else { - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD); - } -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - nic->net_stats.tx_packets++; - nic->net_stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if(pci_dma_mapping_error(rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one, and clearing EL bit of previous. */ - if(rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned(cpu_to_le32(rx->dma_addr), - (u32 *)&prev_rfd->link); - wmb(); - prev_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if(unlikely(!(rfd_status & cb_complete))) - return -ENODATA; - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - /* this allows for a fast restart without re-enabling interrupts */ - if(le16_to_cpu(rfd->command) & cb_el) - nic->ru_running = RU_SUSPENDED; - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if(unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - nic->net_stats.rx_packets++; - nic->net_stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if(work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if(pci_dma_mapping_error(rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one, and clearing EL bit of previous. */ - if(rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned(cpu_to_le32(rx->dma_addr), - (u32 *)&prev_rfd->link); - wmb(); - prev_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0; - struct rx *rx_to_start = NULL; - - /* are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if(RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - int err = e100_rx_indicate(nic, rx, work_done, work_to_do); - if(-EAGAIN == err) { - /* hit quota so have more work to do, restart once - * cleanup is complete */ - restart_required = 0; - break; - } else if(-ENODATA == err) - break; /* No more to clean */ - } - - /* save our starting point as the place we'll restart the receiver */ - if(restart_required) - rx_to_start = nic->rx_to_clean; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - if(restart_required) { - // ack the rnr? - writeb(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, rx_to_start); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = readb(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - writeb(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(!nic->ecdev && likely(netif_rx_schedule_prep(netdev))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - -static int e100_poll(struct net_device *netdev, int *budget) -{ - struct nic *nic = netdev_priv(netdev); - unsigned int work_to_do = min(netdev->quota, *budget); - unsigned int work_done = 0; - int tx_cleaned; - - e100_rx_clean(nic, &work_done, work_to_do); - tx_cleaned = e100_tx_clean(nic); - - /* If no Rx and Tx cleanup work was done, exit polling mode. */ - if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { - netif_rx_complete(netdev); - e100_enable_irq(nic); - return 0; - } - - *budget -= work_done; - netdev->quota -= work_done; - - return 1; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static struct net_device_stats *e100_get_stats(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return &nic->net_stats; -} - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - netif_poll_enable(nic->netdev); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - netif_poll_disable(nic->netdev); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - readb(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); -#define E100_PHY_REGS 0x1C -#define E100_REGS_LEN 1 + E100_PHY_REGS + \ - sizeof(nic->mem->dump_buf) / sizeof(u32) - return E100_REGS_LEN * sizeof(u32); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->rev_id; - buff[0] = readb(&nic->csr->scb.cmd_hi) << 24 | - readb(&nic->csr->scb.cmd_lo) << 16 | - readw(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN sizeof(e100_gstrings_test) / ETH_GSTRING_LEN - -static int e100_diag_test_count(struct net_device *netdev) -{ - return E100_TEST_LEN; -} - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN - -static int e100_get_stats_count(struct net_device *netdev) -{ - return E100_STATS_LEN; -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&nic->net_stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test_count = e100_diag_test_count, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_stats_count = e100_get_stats_count, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->get_stats = e100_get_stats; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - netdev->poll = e100_poll; - netdev->weight = E100_NAPI_WEIGHT; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_MODULE_OWNER(netdev); - SET_NETDEV_DEV(netdev, &pdev->dev); - - nic->csr = ioremap(pci_resource_start(pdev, 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if(!is_valid_ether_addr(netdev->perm_addr)) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) - nic->flags |= wol_magic; - - /* ack any pending wake events, disable PME */ - err = pci_enable_wake(pdev, 0, 0); - if (err) - DPRINTK(PROBE, ERR, "Error clearing wake event\n"); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } else { - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, " - "MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n", - (unsigned long long)pci_resource_start(pdev, 0), pdev->irq, - netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], - netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - iounmap(nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - e100_free(nic); - iounmap(nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - if (netif_running(netdev)) - netif_poll_disable(nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - pci_disable_device(pdev); - free_irq(pdev->irq, netdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return; - - if (netif_running(netdev)) - netif_poll_disable(nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci conneection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adpater I/O. */ - netdev->stop(netdev); - - if (!nic->ecdev) { - /* Detach; put netif into state similar to hotplug unplug. */ - netif_poll_enable(netdev); - netif_device_detach(netdev); - } - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - printk(KERN_INFO DRV_NAME " " DRV_DESCRIPTION " " DRV_VERSION - ", master " EC_MASTER_VERSION "\n"); - - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.20-orig.c b/devices/e100-2.6.20-orig.c deleted file mode 100644 index 0cefef5e..00000000 --- a/devices/e100-2.6.20-orig.c +++ /dev/null @@ -1,2889 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Recieve - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * senario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.17-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __FUNCTION__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - u16 status; - u16 command; - u32 link; - u32 rbd; - u16 actual_size; - u16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - u16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - u16 status; - u16 command; - u32 link; - union { - u8 iaaddr[ETH_ALEN]; - u32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - u32 buf_addr; - u16 size; - u16 eol; - } tbd; - } tcb; - u32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - u32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - u32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - u32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - u16 xmt_tco_frames, rcv_tco_frames; - u32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - u16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct net_device_stats net_stats; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u8 rev_id; - u16 leds; - u16 eeprom_wc; - u16 eeprom[256]; - spinlock_t mdio_lock; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)readb(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - writeb(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - writeb(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - writel(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - writel(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - writel(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - cpu_to_le16(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - writeb(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - writeb(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - writeb(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = readb(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - writeb(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return le16_to_cpu(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += cpu_to_le16(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - checksum = le16_to_cpu(0xBABA - checksum); - if(checksum != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += cpu_to_le16(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = le16_to_cpu(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!readb(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - writel(dma_addr, &nic->csr->scb.gen_ptr); - writeb(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (readl(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id); - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557*/ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = cpu_to_le16(cb_el); - nic->blank_rfd.rbd = 0xFFFFFFFF; - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if(netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if(nic->mac >= mac_82559_D101M) - config->tno_intr = 0x1; /* TCO stats enable */ - else - config->standard_stat_counter = 0x0; - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w rev_id */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interupts, something could have been set */ - writeb(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device_stats *ns = &nic->net_stats; - struct stats *s = &nic->mem->stats; - u32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (u32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so where always waiting for results of the - * previous command. */ - - if(*complete == le32_to_cpu(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - nic->net_stats.tx_packets++; - nic->net_stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if(pci_dma_mapping_error(rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one, and clearing EL bit of previous. */ - if(rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned(cpu_to_le32(rx->dma_addr), - (u32 *)&prev_rfd->link); - wmb(); - prev_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if(unlikely(!(rfd_status & cb_complete))) - return -ENODATA; - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - /* this allows for a fast restart without re-enabling interrupts */ - if(le16_to_cpu(rfd->command) & cb_el) - nic->ru_running = RU_SUSPENDED; - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if(unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - nic->net_stats.rx_packets++; - nic->net_stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - netif_receive_skb(skb); - if(work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0; - struct rx *rx_to_start = NULL; - - /* are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if(RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - int err = e100_rx_indicate(nic, rx, work_done, work_to_do); - if(-EAGAIN == err) { - /* hit quota so have more work to do, restart once - * cleanup is complete */ - restart_required = 0; - break; - } else if(-ENODATA == err) - break; /* No more to clean */ - } - - /* save our starting point as the place we'll restart the receiver */ - if(restart_required) - rx_to_start = nic->rx_to_clean; - - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - if(restart_required) { - // ack the rnr? - writeb(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, rx_to_start); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = readb(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - writeb(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(likely(netif_rx_schedule_prep(netdev))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct net_device *netdev, int *budget) -{ - struct nic *nic = netdev_priv(netdev); - unsigned int work_to_do = min(netdev->quota, *budget); - unsigned int work_done = 0; - int tx_cleaned; - - e100_rx_clean(nic, &work_done, work_to_do); - tx_cleaned = e100_tx_clean(nic); - - /* If no Rx and Tx cleanup work was done, exit polling mode. */ - if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { - netif_rx_complete(netdev); - e100_enable_irq(nic); - return 0; - } - - *budget -= work_done; - netdev->quota -= work_done; - - return 1; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static struct net_device_stats *e100_get_stats(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return &nic->net_stats; -} - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - netif_poll_enable(nic->netdev); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - netif_poll_disable(nic->netdev); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - readb(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); -#define E100_PHY_REGS 0x1C -#define E100_REGS_LEN 1 + E100_PHY_REGS + \ - sizeof(nic->mem->dump_buf) / sizeof(u32) - return E100_REGS_LEN * sizeof(u32); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->rev_id; - buff[0] = readb(&nic->csr->scb.cmd_hi) << 24 | - readb(&nic->csr->scb.cmd_lo) << 16 | - readw(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN sizeof(e100_gstrings_test) / ETH_GSTRING_LEN - -static int e100_diag_test_count(struct net_device *netdev) -{ - return E100_TEST_LEN; -} - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN - -static int e100_get_stats_count(struct net_device *netdev) -{ - return E100_STATS_LEN; -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&nic->net_stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test_count = e100_diag_test_count, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_stats_count = e100_get_stats_count, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->get_stats = e100_get_stats; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - netdev->poll = e100_poll; - netdev->weight = E100_NAPI_WEIGHT; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_MODULE_OWNER(netdev); - SET_NETDEV_DEV(netdev, &pdev->dev); - - nic->csr = ioremap(pci_resource_start(pdev, 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if(!is_valid_ether_addr(netdev->perm_addr)) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) - nic->flags |= wol_magic; - - /* ack any pending wake events, disable PME */ - err = pci_enable_wake(pdev, 0, 0); - if (err) - DPRINTK(PROBE, ERR, "Error clearing wake event\n"); - - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, " - "MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n", - (unsigned long long)pci_resource_start(pdev, 0), pdev->irq, - netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], - netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - iounmap(nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - iounmap(nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - netif_poll_disable(nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - pci_disable_device(pdev); - free_irq(pdev->irq, netdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - netif_poll_disable(nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci conneection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - /* Similar to calling e100_down(), but avoids adpater I/O. */ - netdev->stop(netdev); - - /* Detach; put netif into state similar to hotplug unplug. */ - netif_poll_enable(netdev); - netif_device_detach(netdev); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if(((1 << debug) - 1) & NETIF_MSG_DRV) { - printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.24-ethercat.c b/devices/e100-2.6.24-ethercat.c deleted file mode 100644 index 6b48493c..00000000 --- a/devices/e100-2.6.24-ethercat.c +++ /dev/null @@ -1,3067 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Recieve - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * senario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" - -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k4"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Mario Witkowski "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __FUNCTION__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - u16 status; - u16 command; - u32 link; - u32 rbd; - u16 actual_size; - u16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - u16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - u16 status; - u16 command; - u32 link; - union { - u8 iaaddr[ETH_ALEN]; - u32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - u32 buf_addr; - u16 size; - u16 eol; - } tbd; - } tcb; - u32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - u32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - u32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - u32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - u16 xmt_tco_frames, rcv_tco_frames; - u32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - u16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - u16 eeprom[256]; - spinlock_t mdio_lock; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - cpu_to_le16(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return le16_to_cpu(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += cpu_to_le16(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - checksum = le16_to_cpu(0xBABA - checksum); - if(checksum != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += cpu_to_le16(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = le16_to_cpu(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557*/ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = cpu_to_le16(cb_el); - nic->blank_rfd.rbd = 0xFFFFFFFF; - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w revision */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - u32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (u32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so where always waiting for results of the - * previous command. */ - - if(*complete == le32_to_cpu(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - } else { - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); - } -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if(pci_dma_mapping_error(rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one, and clearing EL bit of previous. */ - if(rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned(cpu_to_le32(rx->dma_addr), - (u32 *)&prev_rfd->link); - wmb(); - prev_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if(unlikely(!(rfd_status & cb_complete))) - return -ENODATA; - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - /* this allows for a fast restart without re-enabling interrupts */ - if(le16_to_cpu(rfd->command) & cb_el) - nic->ru_running = RU_SUSPENDED; - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if(unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if(work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if(pci_dma_mapping_error(rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one, and clearing EL bit of previous. */ - if(rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned(cpu_to_le32(rx->dma_addr), - (u32 *)&prev_rfd->link); - wmb(); - prev_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0; - struct rx *rx_to_start = NULL; - - /* are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if(RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - int err = e100_rx_indicate(nic, rx, work_done, work_to_do); - if(-EAGAIN == err) { - /* hit quota so have more work to do, restart once - * cleanup is complete */ - restart_required = 0; - break; - } else if(-ENODATA == err) - break; /* No more to clean */ - } - - /* save our starting point as the place we'll restart the receiver */ - if(restart_required) - rx_to_start = nic->rx_to_clean; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - if(restart_required) { - // ack the rnr? - writeb(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, rx_to_start); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(!nic->ecdev && likely(netif_rx_schedule_prep(netdev, &nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev, &nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - struct net_device *netdev = nic->netdev; - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(netdev, napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN sizeof(e100_gstrings_test) / ETH_GSTRING_LEN - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - DECLARE_MAC_BUF(mac); - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) - nic->flags |= wol_magic; - - /* ack any pending wake events, disable PME */ - err = pci_enable_wake(pdev, 0, 0); - if (err) - DPRINTK(PROBE, ERR, "Error clearing wake event\n"); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } else { - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, print_mac(mac, netdev->dev_addr)); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - iounmap(nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - if (netif_running(netdev)) - napi_disable(&nic->napi); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - free_irq(pdev->irq, netdev); - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return; - - if (netif_running(netdev)) - napi_disable(&nic->napi); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - free_irq(pdev->irq, netdev); - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci conneection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adpater I/O. */ - netdev->stop(netdev); - - if (!nic->ecdev) { - /* Detach; put netif into state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - } - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - printk(KERN_INFO DRV_NAME " " DRV_DESCRIPTION " " DRV_VERSION - ", master " EC_MASTER_VERSION "\n"); - - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.24-orig.c b/devices/e100-2.6.24-orig.c deleted file mode 100644 index b87402bc..00000000 --- a/devices/e100-2.6.24-orig.c +++ /dev/null @@ -1,2895 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Recieve - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * senario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k4"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __FUNCTION__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - u16 status; - u16 command; - u32 link; - u32 rbd; - u16 actual_size; - u16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - u16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - u16 status; - u16 command; - u32 link; - union { - u8 iaaddr[ETH_ALEN]; - u32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - u32 buf_addr; - u16 size; - u16 eol; - } tbd; - } tcb; - u32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - u32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - u32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - u32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - u16 xmt_tco_frames, rcv_tco_frames; - u32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - u16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - u16 eeprom[256]; - spinlock_t mdio_lock; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - cpu_to_le16(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return le16_to_cpu(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += cpu_to_le16(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - checksum = le16_to_cpu(0xBABA - checksum); - if(checksum != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += cpu_to_le16(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = le16_to_cpu(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557*/ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = cpu_to_le16(cb_el); - nic->blank_rfd.rbd = 0xFFFFFFFF; - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if(netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w revision */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - u32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (u32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so where always waiting for results of the - * previous command. */ - - if(*complete == le32_to_cpu(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if(pci_dma_mapping_error(rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one, and clearing EL bit of previous. */ - if(rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned(cpu_to_le32(rx->dma_addr), - (u32 *)&prev_rfd->link); - wmb(); - prev_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if(unlikely(!(rfd_status & cb_complete))) - return -ENODATA; - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - /* this allows for a fast restart without re-enabling interrupts */ - if(le16_to_cpu(rfd->command) & cb_el) - nic->ru_running = RU_SUSPENDED; - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if(unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - netif_receive_skb(skb); - if(work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0; - struct rx *rx_to_start = NULL; - - /* are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if(RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - int err = e100_rx_indicate(nic, rx, work_done, work_to_do); - if(-EAGAIN == err) { - /* hit quota so have more work to do, restart once - * cleanup is complete */ - restart_required = 0; - break; - } else if(-ENODATA == err) - break; /* No more to clean */ - } - - /* save our starting point as the place we'll restart the receiver */ - if(restart_required) - rx_to_start = nic->rx_to_clean; - - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - if(restart_required) { - // ack the rnr? - writeb(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, rx_to_start); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(likely(netif_rx_schedule_prep(netdev, &nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev, &nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - struct net_device *netdev = nic->netdev; - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(netdev, napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN sizeof(e100_gstrings_test) / ETH_GSTRING_LEN - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - DECLARE_MAC_BUF(mac); - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) - nic->flags |= wol_magic; - - /* ack any pending wake events, disable PME */ - err = pci_enable_wake(pdev, 0, 0); - if (err) - DPRINTK(PROBE, ERR, "Error clearing wake event\n"); - - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, print_mac(mac, netdev->dev_addr)); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - iounmap(nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - napi_disable(&nic->napi); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - free_irq(pdev->irq, netdev); - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - napi_disable(&nic->napi); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - free_irq(pdev->irq, netdev); - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci conneection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adpater I/O. */ - netdev->stop(netdev); - - /* Detach; put netif into state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if(((1 << debug) - 1) & NETIF_MSG_DRV) { - printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.26-ethercat.c b/devices/e100-2.6.26-ethercat.c deleted file mode 100644 index 158da5aa..00000000 --- a/devices/e100-2.6.26-ethercat.c +++ /dev/null @@ -1,3112 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" - -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k4"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Mario Witkowski "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __FUNCTION__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w revision */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if(*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - } else { - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); - } -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (readb(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (readb(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if(unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if(work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - } - - if(restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - if (!nic->ecdev) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(!nic->ecdev && likely(netif_rx_schedule_prep(netdev, &nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev, &nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - struct net_device *netdev = nic->netdev; - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(netdev, napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - DECLARE_MAC_BUF(mac); - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) - nic->flags |= wol_magic; - - /* ack any pending wake events, disable PME */ - err = pci_enable_wake(pdev, 0, 0); - if (err) - DPRINTK(PROBE, ERR, "Error clearing wake event\n"); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } else { - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, print_mac(mac, netdev->dev_addr)); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - e100_suspend(pdev, PMSG_SUSPEND); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adapter I/O. */ - netdev->stop(netdev); - - if (!nic->ecdev) { - /* Detach; put netif into a state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - } - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - printk(KERN_INFO DRV_NAME " " DRV_DESCRIPTION " " DRV_VERSION - ", master " EC_MASTER_VERSION "\n"); - - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.26-orig.c b/devices/e100-2.6.26-orig.c deleted file mode 100644 index 1037b133..00000000 --- a/devices/e100-2.6.26-orig.c +++ /dev/null @@ -1,2942 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k4"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __FUNCTION__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if(netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w revision */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if(*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (readb(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (readb(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if(unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - netif_receive_skb(skb); - if(work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - } - - if(restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(likely(netif_rx_schedule_prep(netdev, &nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev, &nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - struct net_device *netdev = nic->netdev; - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(netdev, napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - DECLARE_MAC_BUF(mac); - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) - nic->flags |= wol_magic; - - /* ack any pending wake events, disable PME */ - err = pci_enable_wake(pdev, 0, 0); - if (err) - DPRINTK(PROBE, ERR, "Error clearing wake event\n"); - - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, print_mac(mac, netdev->dev_addr)); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - e100_suspend(pdev, PMSG_SUSPEND); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adapter I/O. */ - netdev->stop(netdev); - - /* Detach; put netif into a state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if(((1 << debug) - 1) & NETIF_MSG_DRV) { - printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.27-ethercat.c b/devices/e100-2.6.27-ethercat.c deleted file mode 100644 index 206ac50f..00000000 --- a/devices/e100-2.6.27-ethercat.c +++ /dev/null @@ -1,3119 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" - -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k4"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Mario Witkowski "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __FUNCTION__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w revision */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if(*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - } else { - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); - } -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if(unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if(work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - } - - if(restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - if (!nic->ecdev) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(!nic->ecdev && likely(netif_rx_schedule_prep(netdev, &nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev, &nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - struct net_device *netdev = nic->netdev; - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(netdev, napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - DECLARE_MAC_BUF(mac); - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - -#ifdef CONFIG_PCI // avoid compiler error on kernels not supporting PCI - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); -#endif - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } else { - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, print_mac(mac, netdev->dev_addr)); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - if (pci_enable_wake(pdev, PCI_D3cold, true)) - pci_enable_wake(pdev, PCI_D3hot, true); - } else { - pci_enable_wake(pdev, PCI_D3hot, false); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - e100_suspend(pdev, PMSG_SUSPEND); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adapter I/O. */ - netdev->stop(netdev); - - if (!nic->ecdev) { - /* Detach; put netif into a state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - } - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - printk(KERN_INFO DRV_NAME " " DRV_DESCRIPTION " " DRV_VERSION - ", master " EC_MASTER_VERSION "\n"); - - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.27-orig.c b/devices/e100-2.6.27-orig.c deleted file mode 100644 index 2db54a7b..00000000 --- a/devices/e100-2.6.27-orig.c +++ /dev/null @@ -1,2947 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k4"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __FUNCTION__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if(netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w revision */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if(*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if(unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - netif_receive_skb(skb); - if(work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); - } - - if(restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(likely(netif_rx_schedule_prep(netdev, &nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev, &nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - struct net_device *netdev = nic->netdev; - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(netdev, napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - DECLARE_MAC_BUF(mac); - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, print_mac(mac, netdev->dev_addr)); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - if (pci_enable_wake(pdev, PCI_D3cold, true)) - pci_enable_wake(pdev, PCI_D3hot, true); - } else { - pci_enable_wake(pdev, PCI_D3hot, false); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - e100_suspend(pdev, PMSG_SUSPEND); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adapter I/O. */ - netdev->stop(netdev); - - /* Detach; put netif into a state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if(((1 << debug) - 1) & NETIF_MSG_DRV) { - printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.28-ethercat.c b/devices/e100-2.6.28-ethercat.c deleted file mode 100644 index fb74e5fc..00000000 --- a/devices/e100-2.6.28-ethercat.c +++ /dev/null @@ -1,3110 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" - -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k6"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Mario Witkowski "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w revision */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if(*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - } else { - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); - } -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if(unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if(work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if(restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - if (!nic->ecdev) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(!nic->ecdev && likely(netif_rx_schedule_prep(netdev, &nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev, &nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - struct net_device *netdev = nic->netdev; - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(netdev, napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - DECLARE_MAC_BUF(mac); - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) - nic->flags |= wol_magic; - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } else { - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, print_mac(mac, netdev->dev_addr)); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - e100_suspend(pdev, PMSG_SUSPEND); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adapter I/O. */ - netdev->stop(netdev); - - if (!nic->ecdev) { - /* Detach; put netif into a state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - } - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - printk(KERN_INFO DRV_NAME " " DRV_DESCRIPTION " " DRV_VERSION - ", master " EC_MASTER_VERSION "\n"); - - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.28-orig.c b/devices/e100-2.6.28-orig.c deleted file mode 100644 index e8bfcce6..00000000 --- a/devices/e100-2.6.28-orig.c +++ /dev/null @@ -1,2940 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k6"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if(nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if(nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for(j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for(i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if(!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for(addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if(addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if(start + count >= nic->eeprom_wc) - return -EINVAL; - - for(addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for(addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if(likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if(unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if(unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if(unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if(unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while(nic->cb_to_send != nic->cb_to_use) { - if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if(err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if(nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if(nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if(nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if(nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if(netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if(nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - goto noloaducode; - - /* Search for ucode match against h/w revision */ - for (opts = ucode_opts; opts->mac; opts++) { - int i; - u32 *ucode = opts->ucode; - if (nic->mac != opts->mac) - continue; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode | cb_el); - return; - } - -noloaducode: - cb->command = cpu_to_le16(cb_nop | cb_el); -} - -static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for(addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if(addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for(addr = 0; addr < 32; addr++) { - if(addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if(!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if((err = e100_phy_init(nic))) - return err; - if((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for(i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if(netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if(netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if(*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if(nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if(nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if(e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if(duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if(nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if(nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if(nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "full" : "half"); - } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - DPRINTK(LINK, INFO, "link down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if(nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if(nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if(e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch(err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for(cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if(likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if(nic->cbs) { - while(nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if(cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if(!nic->cbs) - return -ENOMEM; - - for(cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if(!nic->rxs) return; - if(RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if(!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if(unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if(unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - nic->netdev->last_rx = jiffies; - netif_receive_skb(skb); - if(work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if(restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if(work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if(nic->rxs) { - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - if(rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for(rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if(e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if(stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(likely(netif_rx_schedule_prep(netdev, &nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev, &nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - struct net_device *netdev = nic->netdev; - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(netdev, napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if((err = e100_rx_alloc_list(nic))) - return err; - if((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if(nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if((err = e100_hw_init(nic))) - goto err_loopback_none; - - if(loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for(i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) - return -EOPNOTSUPP; - - if(wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if(eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if(netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if(netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if(test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if(netif_running(netdev)) - e100_up(nic); - } - for(i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for(i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if(nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - DECLARE_MAC_BUF(mac); - - if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if(((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->open = e100_open; - netdev->stop = e100_close; - netdev->hard_start_xmit = e100_xmit_frame; - netdev->set_multicast_list = e100_set_multicast_list; - netdev->set_mac_address = e100_set_mac_address; - netdev->change_mtu = e100_change_mtu; - netdev->do_ioctl = e100_do_ioctl; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->tx_timeout = e100_tx_timeout; - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = e100_netpoll; -#endif - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if(!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if(ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) - nic->flags |= wol_magic; - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, print_mac(mac, netdev->dev_addr)); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if(netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - e100_suspend(pdev, PMSG_SUSPEND); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adapter I/O. */ - netdev->stop(netdev); - - /* Detach; put netif into a state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if(((1 << debug) - 1) & NETIF_MSG_DRV) { - printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.29-ethercat.c b/devices/e100-2.6.29-ethercat.c deleted file mode 100644 index bbbd9a45..00000000 --- a/devices/e100-2.6.29-ethercat.c +++ /dev/null @@ -1,3013 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" - -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k6"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Mario Witkowski "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw; - u8 timer, bundle, min_size; - int err; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - if (err) { - DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - DPRINTK(PROBE, ERR, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - /* OK, firmware is validated and ready to use... */ - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if (addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for (i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - } else { - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", - nic->netdev->name, - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Down\n", - nic->netdev->name); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); - } -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if (unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if (work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - if (!nic->ecdev) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if(!nic->ecdev && likely(netif_rx_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } else { - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - if (pci_enable_wake(pdev, PCI_D3cold, true)) - pci_enable_wake(pdev, PCI_D3hot, true); - } else { - pci_enable_wake(pdev, PCI_D3hot, false); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return 0; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - e100_suspend(pdev, PMSG_SUSPEND); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adapter I/O. */ - e100_close(netdev); - - if (!nic->ecdev) { - /* Detach; put netif into a state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - } - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - printk(KERN_INFO DRV_NAME " " DRV_DESCRIPTION " " DRV_VERSION - ", master " EC_MASTER_VERSION "\n"); - - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.29-orig.c b/devices/e100-2.6.29-orig.c deleted file mode 100644 index 86bb876f..00000000 --- a/devices/e100-2.6.29-orig.c +++ /dev/null @@ -1,2843 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k6"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw; - u8 timer, bundle, min_size; - int err; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - if (err) { - DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - DPRINTK(PROBE, ERR, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - /* OK, firmware is validated and ready to use... */ - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if (addr == 32) - return -EAGAIN; - - /* Selected the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for (i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", - nic->netdev->name, - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Down\n", - nic->netdev->name); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return 1; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if (unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - netif_receive_skb(skb); - if (work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - /* Alloc new skbs to refill list */ - for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if (unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (likely(netif_rx_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __netif_rx_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - netif_rx_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - strcpy(netdev->name, "eth%d"); - if ((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - if (pci_enable_wake(pdev, PCI_D3cold, true)) - pci_enable_wake(pdev, PCI_D3hot, true); - } else { - pci_enable_wake(pdev, PCI_D3hot, false); - } - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - e100_suspend(pdev, PMSG_SUSPEND); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* Similar to calling e100_down(), but avoids adapter I/O. */ - e100_close(netdev); - - /* Detach; put netif into a state similar to hotplug unplug. */ - napi_enable(&nic->napi); - netif_device_detach(netdev); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if (((1 << debug) - 1) & NETIF_MSG_DRV) { - printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.31-ethercat.c b/devices/e100-2.6.31-ethercat.c deleted file mode 100644 index 2fbef57c..00000000 --- a/devices/e100-2.6.31-ethercat.c +++ /dev/null @@ -1,3232 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" -#include - - -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Florian Pose "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - - __le16 eeprom[256]; - spinlock_t mdio_lock; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw; - u8 timer, bundle, min_size; - int err; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - if (err) { - DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - DPRINTK(PROBE, ERR, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - /* OK, firmware is validated and ready to use... */ - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - DPRINTK(PROBE, INFO, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - DPRINTK(HW, ERR, - "Failed to locate any known PHY, aborting.\n"); - return -EAGAIN; - } - } else - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - - /* Isolate all the PHY ids */ - for (addr = 0; addr < 32; addr++) - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - /* Select the discovered PHY */ - bmcr &= ~BMCR_ISOLATE; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for (i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - } else { - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", - nic->netdev->name, - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Down\n", - nic->netdev->name); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); - } -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if (unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if (work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - if (!nic->ecdev) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (!nic->ecdev && likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } else { - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return -EBUSY; - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return -EBUSY; - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - printk(KERN_INFO DRV_NAME " " DRV_DESCRIPTION " " DRV_VERSION - ", master " EC_MASTER_VERSION "\n"); - - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.31-orig.c b/devices/e100-2.6.31-orig.c deleted file mode 100644 index 3a6735dc..00000000 --- a/devices/e100-2.6.31-orig.c +++ /dev/null @@ -1,3061 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw; - u8 timer, bundle, min_size; - int err; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - if (err) { - DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - DPRINTK(PROBE, ERR, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - /* OK, firmware is validated and ready to use... */ - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - DPRINTK(PROBE, INFO, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - DPRINTK(HW, ERR, - "Failed to locate any known PHY, aborting.\n"); - return -EAGAIN; - } - } else - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - - /* Isolate all the PHY ids */ - for (addr = 0; addr < 32; addr++) - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - /* Select the discovered PHY */ - bmcr &= ~BMCR_ISOLATE; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for (i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", - nic->netdev->name, - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Down\n", - nic->netdev->name); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - netdev->trans_start = jiffies; - return 0; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_free_consistent(nic->pdev, - sizeof(struct cb) * nic->params.cbs.count, - nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_alloc_consistent(nic->pdev, - sizeof(struct cb) * count, &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if (unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - netif_receive_skb(skb); - if (work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - /* Alloc new skbs to refill list */ - for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if (unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - strcpy(netdev->name, "eth%d"); - if ((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - pci_iounmap(pdev, nic->csr); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if (((1 << debug) - 1) & NETIF_MSG_DRV) { - printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.32-ethercat.c b/devices/e100-2.6.32-ethercat.c deleted file mode 100644 index cc131f1a..00000000 --- a/devices/e100-2.6.32-ethercat.c +++ /dev/null @@ -1,3255 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" -#include -#include -#include - - -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Florian Pose "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - struct pci_pool *cbs_pool; - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - - u16 eeprom_wc; - __le16 eeprom[256]; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; - spinlock_t mdio_lock; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - if (nic->ecdev) - return; - - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw; - u8 timer, bundle, min_size; - int err; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - if (err) { - DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - DPRINTK(PROBE, ERR, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - /* OK, firmware is validated and ready to use... */ - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - DPRINTK(PROBE, INFO, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - DPRINTK(HW, ERR, - "Failed to locate any known PHY, aborting.\n"); - return -EAGAIN; - } - } else - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Select the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else if (nic->phy != phy_82552_v) { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - /* - * Workaround for 82552: - * Clear the ISOLATE bit on selected phy_id last (mirrored on all - * other phy_id's) using bmcr value from addr discovery loop above. - */ - if (nic->phy == phy_82552_v) - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for (i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - } else { - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", - nic->netdev->name, - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Down\n", - nic->netdev->name); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); - } -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - netdev->trans_start = jiffies; - return NETDEV_TX_OK; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, - &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - memset(nic->cbs, 0, count * sizeof(struct cb)); - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if (unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if (work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - if (!nic->ecdev) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (!nic->ecdev && likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - - if (!nic->ecdev) { - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - } - - nic->cbs_pool = pci_pool_create(netdev->name, - nic->pdev, - nic->params.cbs.count * sizeof(struct cb), - sizeof(u32), - 0); - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - pci_iounmap(pdev, nic->csr); - pci_pool_destroy(nic->cbs_pool); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) - return -EBUSY; - - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) - return -EBUSY; - - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - printk(KERN_INFO DRV_NAME " " DRV_DESCRIPTION " " DRV_VERSION - ", master " EC_MASTER_VERSION "\n"); - - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.32-orig.c b/devices/e100-2.6.32-orig.c deleted file mode 100644 index 0c53c929..00000000 --- a/devices/e100-2.6.32-orig.c +++ /dev/null @@ -1,3080 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - struct pci_pool *cbs_pool; - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw; - u8 timer, bundle, min_size; - int err; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - if (err) { - DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - DPRINTK(PROBE, ERR, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - /* OK, firmware is validated and ready to use... */ - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - DPRINTK(PROBE, INFO, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - DPRINTK(HW, ERR, - "Failed to locate any known PHY, aborting.\n"); - return -EAGAIN; - } - } else - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Select the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else if (nic->phy != phy_82552_v) { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - /* - * Workaround for 82552: - * Clear the ISOLATE bit on selected phy_id last (mirrored on all - * other phy_id's) using bmcr value from addr discovery loop above. - */ - if (nic->phy == phy_82552_v) - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for (i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", - nic->netdev->name, - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Down\n", - nic->netdev->name); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - netdev->trans_start = jiffies; - return NETDEV_TX_OK; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, - &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - memset(nic->cbs, 0, count * sizeof(struct cb)); - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) - return -ENOMEM; - - /* Align, init, and map the RFD. */ - skb_reserve(rx->skb, NET_IP_ALIGN); - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if (unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - netif_receive_skb(skb); - if (work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - /* Alloc new skbs to refill list */ - for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if (unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - strcpy(netdev->name, "eth%d"); - if ((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - nic->cbs_pool = pci_pool_create(netdev->name, - nic->pdev, - nic->params.cbs.count * sizeof(struct cb), - sizeof(u32), - 0); - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - pci_iounmap(pdev, nic->csr); - pci_pool_destroy(nic->cbs_pool); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if (((1 << debug) - 1) & NETIF_MSG_DRV) { - printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.33-ethercat.c b/devices/e100-2.6.33-ethercat.c deleted file mode 100644 index 35c1a287..00000000 --- a/devices/e100-2.6.33-ethercat.c +++ /dev/null @@ -1,3263 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2008 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Florian Pose "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - struct pci_pool *cbs_pool; - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - - __le16 eeprom[256]; - spinlock_t mdio_lock; - const struct firmware *fw; - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw = nic->fw; - u8 timer, bundle, min_size; - int err = 0; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - /* If the firmware has not previously been loaded, request a pointer - * to it. If it was previously loaded, we are reinitializing the - * adapter, possibly in a resume from hibernate, in which case - * request_firmware() cannot be used. - */ - if (!fw) - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - - if (err) { - DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - DPRINTK(PROBE, ERR, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* OK, firmware is validated and ready to use. Save a pointer - * to it in the nic */ - nic->fw = fw; - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - DPRINTK(PROBE, INFO, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - DPRINTK(HW, ERR, - "Failed to locate any known PHY, aborting.\n"); - return -EAGAIN; - } - } else - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Select the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else if (nic->phy != phy_82552_v) { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - /* - * Workaround for 82552: - * Clear the ISOLATE bit on selected phy_id last (mirrored on all - * other phy_id's) using bmcr value from addr discovery loop above. - */ - if (nic->phy == phy_82552_v) - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for (i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - } else { - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", - nic->netdev->name, - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Down\n", - nic->netdev->name); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); - } -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - netdev->trans_start = jiffies; - return NETDEV_TX_OK; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, - &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - memset(nic->cbs, 0, count * sizeof(struct cb)); - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) - return -ENOMEM; - - /* Init, and map the RFD. */ - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if (unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if (work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - if (!nic->ecdev) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (!nic->ecdev && likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - - if (!nic->ecdev) { - strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - } - - nic->cbs_pool = pci_pool_create(netdev->name, - nic->pdev, - nic->params.cbs.max * sizeof(struct cb), - sizeof(u32), - 0); - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - pci_iounmap(pdev, nic->csr); - pci_pool_destroy(nic->cbs_pool); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return -EBUSY; - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return -EBUSY; - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - printk(KERN_INFO DRV_NAME " " DRV_DESCRIPTION " " DRV_VERSION - ", master " EC_MASTER_VERSION "\n"); - - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.33-orig.c b/devices/e100-2.6.33-orig.c deleted file mode 100644 index a565ea1d..00000000 --- a/devices/e100-2.6.33-orig.c +++ /dev/null @@ -1,3091 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" -#define PFX DRV_NAME ": " - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __func__ , ## args)) - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - struct pci_pool *cbs_pool; - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; - const struct firmware *fw; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - DPRINTK(HW, ERR, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - printk("e100.mdio_ctrl(%s) won't go Ready\n", - nic->netdev->name ); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - DPRINTK(HW, DEBUG, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw = nic->fw; - u8 timer, bundle, min_size; - int err = 0; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - /* If the firmware has not previously been loaded, request a pointer - * to it. If it was previously loaded, we are reinitializing the - * adapter, possibly in a resume from hibernate, in which case - * request_firmware() cannot be used. - */ - if (!fw) - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - - if (err) { - DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - DPRINTK(PROBE, ERR, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* OK, firmware is validated and ready to use. Save a pointer - * to it in the nic */ - nic->fw = fw; - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - DPRINTK(PROBE,ERR, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - DPRINTK(PROBE, INFO, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - DPRINTK(HW, ERR, - "Failed to locate any known PHY, aborting.\n"); - return -EAGAIN; - } - } else - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - - /* Select the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else if (nic->phy != phy_82552_v) { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - /* - * Workaround for 82552: - * Clear the ISOLATE bit on selected phy_id last (mirrored on all - * other phy_id's) using bmcr value from addr discovery loop above. - */ - if (nic->phy == phy_82552_v) - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - DPRINTK(HW, ERR, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for (i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, - ETH_ALEN); -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", - nic->netdev->name, - cmd.speed == SPEED_100 ? "100" : "10", - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - printk(KERN_INFO "e100: %s NIC Link is Down\n", - nic->netdev->name); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - netdev->trans_start = jiffies; - return NETDEV_TX_OK; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, - &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - memset(nic->cbs, 0, count * sizeof(struct cb)); - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) - return -ENOMEM; - - /* Init, and map the RFD. */ - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if (unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - netif_receive_skb(skb); - if (work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - /* Alloc new skbs to refill list */ - for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if (unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", - ioread8(&nic->csr->scb.status)); - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - DPRINTK(PROBE, ERR, "Cannot find proper PCI device " - "base address, aborting.\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - DPRINTK(PROBE, INFO, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - DPRINTK(PROBE, ERR, "Invalid MAC address from " - "EEPROM, aborting.\n"); - err = -EAGAIN; - goto err_out_free; - } else { - DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, " - "you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - strcpy(netdev->name, "eth%d"); - if ((err = register_netdev(netdev))) { - DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); - goto err_out_free; - } - nic->cbs_pool = pci_pool_create(netdev->name, - nic->pdev, - nic->params.cbs.max * sizeof(struct cb), - sizeof(u32), - 0); - DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - pci_iounmap(pdev, nic->csr); - pci_pool_destroy(nic->cbs_pool); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if (((1 << debug) - 1) & NETIF_MSG_DRV) { - printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.35-ethercat.c b/devices/e100-2.6.35-ethercat.c deleted file mode 100644 index 1d935b70..00000000 --- a/devices/e100-2.6.35-ethercat.c +++ /dev/null @@ -1,3290 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2012 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Florian Pose "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static DEFINE_PCI_DEVICE_TABLE(e100_id_table) = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - struct pci_pool *cbs_pool; - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - - __le16 eeprom[256]; - spinlock_t mdio_lock; - const struct firmware *fw; - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - netif_err(nic, hw, nic->netdev, - "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - netif_err(nic, hw, nic->netdev, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - netif_err(nic, probe, nic->netdev, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n"); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw = nic->fw; - u8 timer, bundle, min_size; - int err = 0; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - /* If the firmware has not previously been loaded, request a pointer - * to it. If it was previously loaded, we are reinitializing the - * adapter, possibly in a resume from hibernate, in which case - * request_firmware() cannot be used. - */ - if (!fw) - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - - if (err) { - netif_err(nic, probe, nic->netdev, - "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - netif_err(nic, probe, nic->netdev, - "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - netif_err(nic, probe, nic->netdev, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* OK, firmware is validated and ready to use. Save a pointer - * to it in the nic */ - nic->fw = fw; - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - netif_err(nic, probe, nic->netdev, - "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - netif_err(nic, probe, nic->netdev, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - netif_info(nic, probe, nic->netdev, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - netif_err(nic, hw, nic->netdev, - "Failed to locate any known PHY, aborting\n"); - return -EAGAIN; - } - } else - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "phy_addr = %d\n", nic->mii.phy_id); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "phy ID = 0x%08X\n", nic->phy); - - /* Select the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else if (nic->phy != phy_82552_v) { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - /* - * Workaround for 82552: - * Clear the ISOLATE bit on selected phy_id last (mirrored on all - * other phy_id's) using bmcr value from addr discovery loop above. - */ - if (nic->phy == phy_82552_v) - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - netif_err(nic, hw, nic->netdev, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct netdev_hw_addr *ha; - u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - i = 0; - netdev_for_each_mc_addr(ha, netdev) { - if (i == count) - break; - memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr, - ETH_ALEN); - } -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "mc_count=%d, flags=0x%04X\n", - netdev_mc_count(netdev), netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev_mc_count(netdev) > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - return; - } - - netif_printk(nic, timer, KERN_DEBUG, nic->netdev, - "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - netdev_info(nic->netdev, "NIC Link is Up %u Mbps %s Duplex\n", - cmd.speed == SPEED_100 ? 100 : 10, - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - netdev_info(nic->netdev, "NIC Link is Down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - return NETDEV_TX_OK; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - rmb(); /* read skb after status */ - netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev, - "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, - &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - memset(nic->cbs, 0, count * sizeof(struct cb)); - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) - return -ENOMEM; - - /* Init, and map the RFD. */ - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev, - "status=0x%04X\n", rfd_status); - rmb(); /* read size after status bit */ - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if (unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if (work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - if (!nic->ecdev) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - netif_printk(nic, intr, KERN_DEBUG, nic->netdev, - "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (!nic->ecdev && likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "scb.status=0x%02X\n", ioread8(&nic->csr->scb.status)); - - rtnl_lock(); - if (netif_running(netdev)) { - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); - } - rtnl_unlock(); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - netif_info(nic, drv, nic->netdev, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err __attribute__ ((unused)); - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - netif_err(nic, ifup, nic->netdev, "Cannot open interface, aborting\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - pr_err("Etherdev alloc failed, aborting\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - netif_err(nic, probe, nic->netdev, "Cannot enable PCI device, aborting\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - netif_err(nic, probe, nic->netdev, "Cannot find proper PCI device base address, aborting\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - netif_err(nic, probe, nic->netdev, "Cannot obtain PCI resources, aborting\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - netif_err(nic, probe, nic->netdev, "No usable DMA configuration, aborting\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - netif_info(nic, probe, nic->netdev, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - netif_err(nic, probe, nic->netdev, "Cannot map device registers, aborting\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - netif_err(nic, probe, nic->netdev, "Cannot alloc driver memory, aborting\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, aborting\n"); - err = -EAGAIN; - goto err_out_free; - } else { - netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - - if (!nic->ecdev) { - strcpy(netdev->name, "eth%d"); - if ((err = register_netdev(netdev))) { - netif_err(nic, probe, nic->netdev, - "Cannot register net device, aborting\n"); - goto err_out_free; - } - } - - nic->cbs_pool = pci_pool_create(netdev->name, - nic->pdev, - nic->params.cbs.max * sizeof(struct cb), - sizeof(u32), - 0); - netif_info(nic, probe, nic->netdev, - "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - pci_iounmap(pdev, nic->csr); - pci_pool_destroy(nic->cbs_pool); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return -EBUSY; - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return -EBUSY; - - if (pci_enable_device(pdev)) { - pr_err("Cannot re-enable PCI device after reset\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if (((1 << debug) - 1) & NETIF_MSG_DRV) { - pr_info("%s %s, %s\n", DRV_NAME, DRV_DESCRIPTION, DRV_VERSION); - pr_info("%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.35-orig.c b/devices/e100-2.6.35-orig.c deleted file mode 100644 index 8e2eab4e..00000000 --- a/devices/e100-2.6.35-orig.c +++ /dev/null @@ -1,3115 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static DEFINE_PCI_DEVICE_TABLE(e100_id_table) = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - struct pci_pool *cbs_pool; - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; - const struct firmware *fw; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - netif_err(nic, hw, nic->netdev, - "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - netif_err(nic, hw, nic->netdev, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - netif_err(nic, probe, nic->netdev, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n"); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw = nic->fw; - u8 timer, bundle, min_size; - int err = 0; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - /* If the firmware has not previously been loaded, request a pointer - * to it. If it was previously loaded, we are reinitializing the - * adapter, possibly in a resume from hibernate, in which case - * request_firmware() cannot be used. - */ - if (!fw) - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - - if (err) { - netif_err(nic, probe, nic->netdev, - "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - netif_err(nic, probe, nic->netdev, - "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - netif_err(nic, probe, nic->netdev, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* OK, firmware is validated and ready to use. Save a pointer - * to it in the nic */ - nic->fw = fw; - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - netif_err(nic, probe, nic->netdev, - "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - netif_err(nic, probe, nic->netdev, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - netif_info(nic, probe, nic->netdev, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - netif_err(nic, hw, nic->netdev, - "Failed to locate any known PHY, aborting\n"); - return -EAGAIN; - } - } else - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "phy_addr = %d\n", nic->mii.phy_id); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "phy ID = 0x%08X\n", nic->phy); - - /* Select the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else if (nic->phy != phy_82552_v) { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - /* - * Workaround for 82552: - * Clear the ISOLATE bit on selected phy_id last (mirrored on all - * other phy_id's) using bmcr value from addr discovery loop above. - */ - if (nic->phy == phy_82552_v) - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - netif_err(nic, hw, nic->netdev, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct netdev_hw_addr *ha; - u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - i = 0; - netdev_for_each_mc_addr(ha, netdev) { - if (i == count) - break; - memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr, - ETH_ALEN); - } -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "mc_count=%d, flags=0x%04X\n", - netdev_mc_count(netdev), netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev_mc_count(netdev) > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - netif_printk(nic, timer, KERN_DEBUG, nic->netdev, - "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - netdev_info(nic->netdev, "NIC Link is Up %u Mbps %s Duplex\n", - cmd.speed == SPEED_100 ? 100 : 10, - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - netdev_info(nic->netdev, "NIC Link is Down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - return NETDEV_TX_OK; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - rmb(); /* read skb after status */ - netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev, - "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, - &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - memset(nic->cbs, 0, count * sizeof(struct cb)); - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) - return -ENOMEM; - - /* Init, and map the RFD. */ - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev, - "status=0x%04X\n", rfd_status); - rmb(); /* read size after status bit */ - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if (unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - netif_receive_skb(skb); - if (work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - /* Alloc new skbs to refill list */ - for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if (unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - netif_printk(nic, intr, KERN_DEBUG, nic->netdev, - "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "scb.status=0x%02X\n", ioread8(&nic->csr->scb.status)); - - rtnl_lock(); - if (netif_running(netdev)) { - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); - } - rtnl_unlock(); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - netif_info(nic, drv, nic->netdev, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - netif_err(nic, ifup, nic->netdev, "Cannot open interface, aborting\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - pr_err("Etherdev alloc failed, aborting\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - netif_err(nic, probe, nic->netdev, "Cannot enable PCI device, aborting\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - netif_err(nic, probe, nic->netdev, "Cannot find proper PCI device base address, aborting\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - netif_err(nic, probe, nic->netdev, "Cannot obtain PCI resources, aborting\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - netif_err(nic, probe, nic->netdev, "No usable DMA configuration, aborting\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - netif_info(nic, probe, nic->netdev, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - netif_err(nic, probe, nic->netdev, "Cannot map device registers, aborting\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - netif_err(nic, probe, nic->netdev, "Cannot alloc driver memory, aborting\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, aborting\n"); - err = -EAGAIN; - goto err_out_free; - } else { - netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - strcpy(netdev->name, "eth%d"); - if ((err = register_netdev(netdev))) { - netif_err(nic, probe, nic->netdev, "Cannot register net device, aborting\n"); - goto err_out_free; - } - nic->cbs_pool = pci_pool_create(netdev->name, - nic->pdev, - nic->params.cbs.max * sizeof(struct cb), - sizeof(u32), - 0); - netif_info(nic, probe, nic->netdev, - "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - pci_iounmap(pdev, nic->csr); - pci_pool_destroy(nic->cbs_pool); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - pr_err("Cannot re-enable PCI device after reset\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if (((1 << debug) - 1) & NETIF_MSG_DRV) { - pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - pr_info("%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.37-ethercat.c b/devices/e100-2.6.37-ethercat.c deleted file mode 100644 index c536f007..00000000 --- a/devices/e100-2.6.37-ethercat.c +++ /dev/null @@ -1,3290 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2007-2012 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * The IgH EtherCAT Master is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * --- - * - * The license mentioned above concerns the source code only. Using the - * EtherCAT technology and brand is only permitted in compliance with the - * industrial property and similar rights of Beckhoff Automation GmbH. - * - * --- - * - * vim: noexpandtab - * - *****************************************************************************/ - -/** - \file - EtherCAT driver for e100-compatible NICs. -*/ - -/* Former documentation: */ - -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// EtherCAT includes -#include "../globals.h" -#include "ecdev.h" - -#define DRV_NAME "ec_e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("Florian Pose "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION ", master " EC_MASTER_VERSION); - -void e100_ec_poll(struct net_device *); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static DEFINE_PCI_DEVICE_TABLE(e100_id_table) = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; - -// prevent from being loaded automatically -//MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - struct pci_pool *cbs_pool; - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - - __le16 eeprom[256]; - spinlock_t mdio_lock; - const struct firmware *fw; - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - if (nic->ecdev) - return; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - netif_err(nic, hw, nic->netdev, - "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - netif_err(nic, hw, nic->netdev, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - netif_err(nic, probe, nic->netdev, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags = 0; - unsigned int i; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags = 0; - int err = 0; - - if (!nic->ecdev) - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags = 0; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - if (!nic->ecdev) - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n"); - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - if (!nic->ecdev) - spin_unlock_irqrestore(&nic->mdio_lock, flags); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (nic->ecdev || - (netif_running(nic->netdev) || !(nic->flags & wol_magic))) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw = nic->fw; - u8 timer, bundle, min_size; - int err = 0; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - /* If the firmware has not previously been loaded, request a pointer - * to it. If it was previously loaded, we are reinitializing the - * adapter, possibly in a resume from hibernate, in which case - * request_firmware() cannot be used. - */ - if (!fw) - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - - if (err) { - netif_err(nic, probe, nic->netdev, - "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - netif_err(nic, probe, nic->netdev, - "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - netif_err(nic, probe, nic->netdev, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* OK, firmware is validated and ready to use. Save a pointer - * to it in the nic */ - nic->fw = fw; - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - netif_err(nic, probe, nic->netdev, - "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - netif_err(nic, probe, nic->netdev, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - netif_info(nic, probe, nic->netdev, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - netif_err(nic, hw, nic->netdev, - "Failed to locate any known PHY, aborting\n"); - return -EAGAIN; - } - } else - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "phy_addr = %d\n", nic->mii.phy_id); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "phy ID = 0x%08X\n", nic->phy); - - /* Select the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else if (nic->phy != phy_82552_v) { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - /* - * Workaround for 82552: - * Clear the ISOLATE bit on selected phy_id last (mirrored on all - * other phy_id's) using bmcr value from addr discovery loop above. - */ - if (nic->phy == phy_82552_v) - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - netif_err(nic, hw, nic->netdev, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct netdev_hw_addr *ha; - u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - i = 0; - netdev_for_each_mc_addr(ha, netdev) { - if (i == count) - break; - memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr, - ETH_ALEN); - } -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "mc_count=%d, flags=0x%04X\n", - netdev_mc_count(netdev), netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev_mc_count(netdev) > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); - return; - } - - netif_printk(nic, timer, KERN_DEBUG, nic->netdev, - "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - netdev_info(nic->netdev, "NIC Link is Up %u Mbps %s Duplex\n", - cmd.speed == SPEED_100 ? 100 : 10, - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - netdev_info(nic->netdev, "NIC Link is Down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "No space for CB\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - return NETDEV_TX_OK; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - if (!nic->ecdev) - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - rmb(); /* read skb after status */ - netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev, - "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - if (!nic->ecdev) { - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - } - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - if (!nic->ecdev) - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, - &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - memset(nic->cbs, 0, count * sizeof(struct cb)); - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) - return -ENOMEM; - - /* Init, and map the RFD. */ - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev, - "status=0x%04X\n", rfd_status); - rmb(); /* read size after status bit */ - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - if (!nic->ecdev) { - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - } - - if (unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - if (!nic->ecdev) - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - if (nic->ecdev) { - ecdev_receive(nic->ecdev, - skb->data + sizeof(struct rfd), actual_size); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - nic->ec_watchdog_jiffies = jiffies; - } else { - netif_receive_skb(skb); - } - if (work_done) - (*work_done)++; - } - - if (nic->ecdev) { - // make receive frame descriptior usable again - memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - rx->dma_addr = 0; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); - } - } else { - rx->skb = NULL; - } - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - if (!nic->ecdev) { - /* Alloc new skbs to refill list */ - for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if(unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - - if (!nic->ecdev) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - netif_printk(nic, intr, KERN_DEBUG, nic->netdev, - "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (!nic->ecdev && likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -void e100_ec_poll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_rx_clean(nic, NULL, 100); - e100_tx_clean(nic); - - if (jiffies - nic->ec_watchdog_jiffies >= 2 * HZ) { - e100_watchdog((unsigned long) nic); - nic->ec_watchdog_jiffies = jiffies; - } -} - - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - if (!nic->ecdev) { - mod_timer(&nic->watchdog, jiffies); - } - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - if (!nic->ecdev) { - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - } - return 0; - -err_no_irq: - if (!nic->ecdev) - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - if (!nic->ecdev) { - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - } - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - } - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "scb.status=0x%02X\n", ioread8(&nic->csr->scb.status)); - - rtnl_lock(); - if (netif_running(netdev)) { - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); - } - rtnl_unlock(); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - netif_info(nic, drv, nic->netdev, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err __attribute__ ((unused)); - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - if (!nic->ecdev) - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - netif_err(nic, ifup, nic->netdev, "Cannot open interface, aborting\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - pr_err("Etherdev alloc failed, aborting\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - netif_err(nic, probe, nic->netdev, "Cannot enable PCI device, aborting\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - netif_err(nic, probe, nic->netdev, "Cannot find proper PCI device base address, aborting\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - netif_err(nic, probe, nic->netdev, "Cannot obtain PCI resources, aborting\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - netif_err(nic, probe, nic->netdev, "No usable DMA configuration, aborting\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - netif_info(nic, probe, nic->netdev, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - netif_err(nic, probe, nic->netdev, "Cannot map device registers, aborting\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - netif_err(nic, probe, nic->netdev, "Cannot alloc driver memory, aborting\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, aborting\n"); - err = -EAGAIN; - goto err_out_free; - } else { - netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); - - if (!nic->ecdev) { - strcpy(netdev->name, "eth%d"); - if ((err = register_netdev(netdev))) { - netif_err(nic, probe, nic->netdev, - "Cannot register net device, aborting\n"); - goto err_out_free; - } - } - - nic->cbs_pool = pci_pool_create(netdev->name, - nic->pdev, - nic->params.cbs.max * sizeof(struct cb), - sizeof(u32), - 0); - netif_info(nic, probe, nic->netdev, - "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); - if (err) { - ecdev_withdraw(nic->ecdev); - goto err_out_free; - } - } - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); - } else { - unregister_netdev(netdev); - } - - e100_free(nic); - pci_iounmap(pdev, nic->csr); - pci_pool_destroy(nic->cbs_pool); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return -EBUSY; - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (nic->ecdev) - return -EBUSY; - - if (pci_enable_device(pdev)) { - pr_err("Cannot re-enable PCI device after reset\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - if (!nic->ecdev) - netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { - e100_open(netdev); - if (!nic->ecdev) - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if (((1 << debug) - 1) & NETIF_MSG_DRV) { - pr_info("%s %s, %s\n", DRV_NAME, DRV_DESCRIPTION, DRV_VERSION); - pr_info("%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - printk(KERN_INFO DRV_NAME " cleaning up module...\n"); - pci_unregister_driver(&e100_driver); - printk(KERN_INFO DRV_NAME " module cleaned up.\n"); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/e100-2.6.37-orig.c b/devices/e100-2.6.37-orig.c deleted file mode 100644 index b0aa9e68..00000000 --- a/devices/e100-2.6.37-orig.c +++ /dev/null @@ -1,3115 +0,0 @@ -/******************************************************************************* - - Intel PRO/100 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* - * e100.c: Intel(R) PRO/100 ethernet driver - * - * (Re)written 2003 by scott.feldman@intel.com. Based loosely on - * original e100 driver, but better described as a munging of - * e100, e1000, eepro100, tg3, 8139cp, and other drivers. - * - * References: - * Intel 8255x 10/100 Mbps Ethernet Controller Family, - * Open Source Software Developers Manual, - * http://sourceforge.net/projects/e1000 - * - * - * Theory of Operation - * - * I. General - * - * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet - * controller family, which includes the 82557, 82558, 82559, 82550, - * 82551, and 82562 devices. 82558 and greater controllers - * integrate the Intel 82555 PHY. The controllers are used in - * server and client network interface cards, as well as in - * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx - * configurations. 8255x supports a 32-bit linear addressing - * mode and operates at 33Mhz PCI clock rate. - * - * II. Driver Operation - * - * Memory-mapped mode is used exclusively to access the device's - * shared-memory structure, the Control/Status Registers (CSR). All - * setup, configuration, and control of the device, including queuing - * of Tx, Rx, and configuration commands is through the CSR. - * cmd_lock serializes accesses to the CSR command register. cb_lock - * protects the shared Command Block List (CBL). - * - * 8255x is highly MII-compliant and all access to the PHY go - * through the Management Data Interface (MDI). Consequently, the - * driver leverages the mii.c library shared with other MII-compliant - * devices. - * - * Big- and Little-Endian byte order as well as 32- and 64-bit - * archs are supported. Weak-ordered memory and non-cache-coherent - * archs are supported. - * - * III. Transmit - * - * A Tx skb is mapped and hangs off of a TCB. TCBs are linked - * together in a fixed-size ring (CBL) thus forming the flexible mode - * memory structure. A TCB marked with the suspend-bit indicates - * the end of the ring. The last TCB processed suspends the - * controller, and the controller can be restarted by issue a CU - * resume command to continue from the suspend point, or a CU start - * command to start at a given position in the ring. - * - * Non-Tx commands (config, multicast setup, etc) are linked - * into the CBL ring along with Tx commands. The common structure - * used for both Tx and non-Tx commands is the Command Block (CB). - * - * cb_to_use is the next CB to use for queuing a command; cb_to_clean - * is the next CB to check for completion; cb_to_send is the first - * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt. - * cbs_avail keeps track of number of free CB resources available. - * - * Hardware padding of short packets to minimum packet size is - * enabled. 82557 pads with 7Eh, while the later controllers pad - * with 00h. - * - * IV. Receive - * - * The Receive Frame Area (RFA) comprises a ring of Receive Frame - * Descriptors (RFD) + data buffer, thus forming the simplified mode - * memory structure. Rx skbs are allocated to contain both the RFD - * and the data buffer, but the RFD is pulled off before the skb is - * indicated. The data buffer is aligned such that encapsulated - * protocol headers are u32-aligned. Since the RFD is part of the - * mapped shared memory, and completion status is contained within - * the RFD, the RFD must be dma_sync'ed to maintain a consistent - * view from software and hardware. - * - * In order to keep updates to the RFD link field from colliding with - * hardware writes to mark packets complete, we use the feature that - * hardware will not write to a size 0 descriptor and mark the previous - * packet as end-of-list (EL). After updating the link, we remove EL - * and only then restore the size such that hardware may use the - * previous-to-end RFD. - * - * Under typical operation, the receive unit (RU) is start once, - * and the controller happily fills RFDs as frames arrive. If - * replacement RFDs cannot be allocated, or the RU goes non-active, - * the RU must be restarted. Frame arrival generates an interrupt, - * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. A software-generated interrupt - * is generated from the watchdog to recover from a failed allocation - * scenario where all Rx resources have been indicated and none re- - * placed. - * - * V. Miscellaneous - * - * VLAN offloading of tagging, stripping and filtering is not - * supported, but driver will accommodate the extra 4-byte VLAN tag - * for processing by upper layers. Tx/Rx Checksum offloading is not - * supported. Tx Scatter/Gather is not supported. Jumbo Frames is - * not supported (hardware limitation). - * - * MagicPacket(tm) WoL support is enabled/disabled via ethtool. - * - * Thanks to JC (jchapman@katalix.com) for helping with - * testing/troubleshooting the development driver. - * - * TODO: - * o several entry points race with dev->close - * o check for tx-no-resources/stop Q races with tx clean/wake Q - * - * FIXES: - * 2005/12/02 - Michael O'Donnell - * - Stratus87247: protect MDI control register manipulations - * 2009/06/01 - Andreas Mohr - * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "e100" -#define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.24-k2"DRV_EXT -#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" - -#define E100_WATCHDOG_PERIOD (2 * HZ) -#define E100_NAPI_WEIGHT 16 - -#define FIRMWARE_D101M "e100/d101m_ucode.bin" -#define FIRMWARE_D101S "e100/d101s_ucode.bin" -#define FIRMWARE_D102E "e100/d102e_ucode.bin" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_FIRMWARE(FIRMWARE_D101M); -MODULE_FIRMWARE(FIRMWARE_D101S); -MODULE_FIRMWARE(FIRMWARE_D102E); - -static int debug = 3; -static int eeprom_bad_csum_allow = 0; -static int use_io = 0; -module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); -MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); - -#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ - PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ - PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static DEFINE_PCI_DEVICE_TABLE(e100_id_table) = { - INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), - INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), - INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), - INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), - INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), - INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), - INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), - INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), - INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), - INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), - INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), - INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), - INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), - INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -enum mac { - mac_82557_D100_A = 0, - mac_82557_D100_B = 1, - mac_82557_D100_C = 2, - mac_82558_D101_A4 = 4, - mac_82558_D101_B0 = 5, - mac_82559_D101M = 8, - mac_82559_D101S = 9, - mac_82550_D102 = 12, - mac_82550_D102_C = 13, - mac_82551_E = 14, - mac_82551_F = 15, - mac_82551_10 = 16, - mac_unknown = 0xFF, -}; - -enum phy { - phy_100a = 0x000003E0, - phy_100c = 0x035002A8, - phy_82555_tx = 0x015002A8, - phy_nsc_tx = 0x5C002000, - phy_82562_et = 0x033002A8, - phy_82562_em = 0x032002A8, - phy_82562_ek = 0x031002A8, - phy_82562_eh = 0x017002A8, - phy_82552_v = 0xd061004d, - phy_unknown = 0xFFFFFFFF, -}; - -/* CSR (Control/Status Registers) */ -struct csr { - struct { - u8 status; - u8 stat_ack; - u8 cmd_lo; - u8 cmd_hi; - u32 gen_ptr; - } scb; - u32 port; - u16 flash_ctrl; - u8 eeprom_ctrl_lo; - u8 eeprom_ctrl_hi; - u32 mdi_ctrl; - u32 rx_dma_count; -}; - -enum scb_status { - rus_no_res = 0x08, - rus_ready = 0x10, - rus_mask = 0x3C, -}; - -enum ru_state { - RU_SUSPENDED = 0, - RU_RUNNING = 1, - RU_UNINITIALIZED = -1, -}; - -enum scb_stat_ack { - stat_ack_not_ours = 0x00, - stat_ack_sw_gen = 0x04, - stat_ack_rnr = 0x10, - stat_ack_cu_idle = 0x20, - stat_ack_frame_rx = 0x40, - stat_ack_cu_cmd_done = 0x80, - stat_ack_not_present = 0xFF, - stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), - stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), -}; - -enum scb_cmd_hi { - irq_mask_none = 0x00, - irq_mask_all = 0x01, - irq_sw_gen = 0x02, -}; - -enum scb_cmd_lo { - cuc_nop = 0x00, - ruc_start = 0x01, - ruc_load_base = 0x06, - cuc_start = 0x10, - cuc_resume = 0x20, - cuc_dump_addr = 0x40, - cuc_dump_stats = 0x50, - cuc_load_base = 0x60, - cuc_dump_reset = 0x70, -}; - -enum cuc_dump { - cuc_dump_complete = 0x0000A005, - cuc_dump_reset_complete = 0x0000A007, -}; - -enum port { - software_reset = 0x0000, - selftest = 0x0001, - selective_reset = 0x0002, -}; - -enum eeprom_ctrl_lo { - eesk = 0x01, - eecs = 0x02, - eedi = 0x04, - eedo = 0x08, -}; - -enum mdi_ctrl { - mdi_write = 0x04000000, - mdi_read = 0x08000000, - mdi_ready = 0x10000000, -}; - -enum eeprom_op { - op_write = 0x05, - op_read = 0x06, - op_ewds = 0x10, - op_ewen = 0x13, -}; - -enum eeprom_offsets { - eeprom_cnfg_mdix = 0x03, - eeprom_phy_iface = 0x06, - eeprom_id = 0x0A, - eeprom_config_asf = 0x0D, - eeprom_smbus_addr = 0x90, -}; - -enum eeprom_cnfg_mdix { - eeprom_mdix_enabled = 0x0080, -}; - -enum eeprom_phy_iface { - NoSuchPhy = 0, - I82553AB, - I82553C, - I82503, - DP83840, - S80C240, - S80C24, - I82555, - DP83840A = 10, -}; - -enum eeprom_id { - eeprom_id_wol = 0x0020, -}; - -enum eeprom_config_asf { - eeprom_asf = 0x8000, - eeprom_gcl = 0x4000, -}; - -enum cb_status { - cb_complete = 0x8000, - cb_ok = 0x2000, -}; - -enum cb_command { - cb_nop = 0x0000, - cb_iaaddr = 0x0001, - cb_config = 0x0002, - cb_multi = 0x0003, - cb_tx = 0x0004, - cb_ucode = 0x0005, - cb_dump = 0x0006, - cb_tx_sf = 0x0008, - cb_cid = 0x1f00, - cb_i = 0x2000, - cb_s = 0x4000, - cb_el = 0x8000, -}; - -struct rfd { - __le16 status; - __le16 command; - __le32 link; - __le32 rbd; - __le16 actual_size; - __le16 size; -}; - -struct rx { - struct rx *next, *prev; - struct sk_buff *skb; - dma_addr_t dma_addr; -}; - -#if defined(__BIG_ENDIAN_BITFIELD) -#define X(a,b) b,a -#else -#define X(a,b) a,b -#endif -struct config { -/*0*/ u8 X(byte_count:6, pad0:2); -/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); -/*2*/ u8 adaptive_ifs; -/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), - term_write_cache_line:1), pad3:4); -/*4*/ u8 X(rx_dma_max_count:7, pad4:1); -/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); -/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), - tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), - rx_discard_overruns:1), rx_save_bad_frames:1); -/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), - pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), - tx_dynamic_tbd:1); -/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); -/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), - link_status_wake:1), arp_wake:1), mcmatch_wake:1); -/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), - loopback:2); -/*11*/ u8 X(linear_priority:3, pad11:5); -/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); -/*13*/ u8 ip_addr_lo; -/*14*/ u8 ip_addr_hi; -/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), - wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), - pad15_2:1), crs_or_cdt:1); -/*16*/ u8 fc_delay_lo; -/*17*/ u8 fc_delay_hi; -/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), - rx_long_ok:1), fc_priority_threshold:3), pad18:1); -/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), - fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), - full_duplex_force:1), full_duplex_pin:1); -/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); -/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); -/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); - u8 pad_d102[9]; -}; - -#define E100_MAX_MULTICAST_ADDRS 64 -struct multi { - __le16 count; - u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; -}; - -/* Important: keep total struct u32-aligned */ -#define UCODE_SIZE 134 -struct cb { - __le16 status; - __le16 command; - __le32 link; - union { - u8 iaaddr[ETH_ALEN]; - __le32 ucode[UCODE_SIZE]; - struct config config; - struct multi multi; - struct { - u32 tbd_array; - u16 tcb_byte_count; - u8 threshold; - u8 tbd_count; - struct { - __le32 buf_addr; - __le16 size; - u16 eol; - } tbd; - } tcb; - __le32 dump_buffer_addr; - } u; - struct cb *next, *prev; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum loopback { - lb_none = 0, lb_mac = 1, lb_phy = 3, -}; - -struct stats { - __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, - tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, - tx_multiple_collisions, tx_total_collisions; - __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, - rx_resource_errors, rx_overrun_errors, rx_cdt_errors, - rx_short_frame_errors; - __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; - __le16 xmt_tco_frames, rcv_tco_frames; - __le32 complete; -}; - -struct mem { - struct { - u32 signature; - u32 result; - } selftest; - struct stats stats; - u8 dump_buf[596]; -}; - -struct param_range { - u32 min; - u32 max; - u32 count; -}; - -struct params { - struct param_range rfds; - struct param_range cbs; -}; - -struct nic { - /* Begin: frequently used values: keep adjacent for cache effect */ - u32 msg_enable ____cacheline_aligned; - struct net_device *netdev; - struct pci_dev *pdev; - u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); - - struct rx *rxs ____cacheline_aligned; - struct rx *rx_to_use; - struct rx *rx_to_clean; - struct rfd blank_rfd; - enum ru_state ru_running; - - spinlock_t cb_lock ____cacheline_aligned; - spinlock_t cmd_lock; - struct csr __iomem *csr; - enum scb_cmd_lo cuc_cmd; - unsigned int cbs_avail; - struct napi_struct napi; - struct cb *cbs; - struct cb *cb_to_use; - struct cb *cb_to_send; - struct cb *cb_to_clean; - __le16 tx_command; - /* End: frequently used values: keep adjacent for cache effect */ - - enum { - ich = (1 << 0), - promiscuous = (1 << 1), - multicast_all = (1 << 2), - wol_magic = (1 << 3), - ich_10h_workaround = (1 << 4), - } flags ____cacheline_aligned; - - enum mac mac; - enum phy phy; - struct params params; - struct timer_list watchdog; - struct timer_list blink_timer; - struct mii_if_info mii; - struct work_struct tx_timeout_task; - enum loopback loopback; - - struct mem *mem; - dma_addr_t dma_addr; - - struct pci_pool *cbs_pool; - dma_addr_t cbs_dma_addr; - u8 adaptive_ifs; - u8 tx_threshold; - u32 tx_frames; - u32 tx_collisions; - u32 tx_deferred; - u32 tx_single_collisions; - u32 tx_multiple_collisions; - u32 tx_fc_pause; - u32 tx_tco_frames; - - u32 rx_fc_pause; - u32 rx_fc_unsupported; - u32 rx_tco_frames; - u32 rx_over_length_errors; - - u16 leds; - u16 eeprom_wc; - __le16 eeprom[256]; - spinlock_t mdio_lock; - const struct firmware *fw; -}; - -static inline void e100_write_flush(struct nic *nic) -{ - /* Flush previous PCI writes through intermediate bridges - * by doing a benign read */ - (void)ioread8(&nic->csr->scb.status); -} - -static void e100_enable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_disable_irq(struct nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&nic->cmd_lock, flags); - iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irqrestore(&nic->cmd_lock, flags); -} - -static void e100_hw_reset(struct nic *nic) -{ - /* Put CU and RU into idle with a selective reset to get - * device off of PCI bus */ - iowrite32(selective_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Now fully reset device */ - iowrite32(software_reset, &nic->csr->port); - e100_write_flush(nic); udelay(20); - - /* Mask off our interrupt line - it's unmasked after reset */ - e100_disable_irq(nic); -} - -static int e100_self_test(struct nic *nic) -{ - u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); - - /* Passing the self-test is a pretty good indication - * that the device can DMA to/from host memory */ - - nic->mem->selftest.signature = 0; - nic->mem->selftest.result = 0xFFFFFFFF; - - iowrite32(selftest | dma_addr, &nic->csr->port); - e100_write_flush(nic); - /* Wait 10 msec for self-test to complete */ - msleep(10); - - /* Interrupts are enabled after self-test */ - e100_disable_irq(nic); - - /* Check results of self-test */ - if (nic->mem->selftest.result != 0) { - netif_err(nic, hw, nic->netdev, - "Self-test failed: result=0x%08X\n", - nic->mem->selftest.result); - return -ETIMEDOUT; - } - if (nic->mem->selftest.signature == 0) { - netif_err(nic, hw, nic->netdev, "Self-test failed: timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) -{ - u32 cmd_addr_data[3]; - u8 ctrl; - int i, j; - - /* Three cmds: write/erase enable, write data, write/erase disable */ - cmd_addr_data[0] = op_ewen << (addr_len - 2); - cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | - le16_to_cpu(data); - cmd_addr_data[2] = op_ewds << (addr_len - 2); - - /* Bit-bang cmds to write word to eeprom */ - for (j = 0; j < 3; j++) { - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data[j] & (1 << i)) ? - eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } - /* Wait 10 msec for cmd to complete */ - msleep(10); - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - } -}; - -/* General technique stolen from the eepro100 driver - very clever */ -static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) -{ - u32 cmd_addr_data; - u16 data = 0; - u8 ctrl; - int i; - - cmd_addr_data = ((op_read << *addr_len) | addr) << 16; - - /* Chip select */ - iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Bit-bang to read word from eeprom */ - for (i = 31; i >= 0; i--) { - ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; - iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - /* Eeprom drives a dummy zero to EEDO after receiving - * complete address. Use this to adjust addr_len. */ - ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); - if (!(ctrl & eedo) && i > 16) { - *addr_len -= (i - 16); - i = 17; - } - - data = (data << 1) | (ctrl & eedo ? 1 : 0); - } - - /* Chip deselect */ - iowrite8(0, &nic->csr->eeprom_ctrl_lo); - e100_write_flush(nic); udelay(4); - - return cpu_to_le16(data); -}; - -/* Load entire EEPROM image into driver cache and validate checksum */ -static int e100_eeprom_load(struct nic *nic) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - for (addr = 0; addr < nic->eeprom_wc; addr++) { - nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); - if (addr < nic->eeprom_wc - 1) - checksum += le16_to_cpu(nic->eeprom[addr]); - } - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { - netif_err(nic, probe, nic->netdev, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; - } - - return 0; -} - -/* Save (portion of) driver EEPROM cache to device and update checksum */ -static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) -{ - u16 addr, addr_len = 8, checksum = 0; - - /* Try reading with an 8-bit addr len to discover actual addr len */ - e100_eeprom_read(nic, &addr_len, 0); - nic->eeprom_wc = 1 << addr_len; - - if (start + count >= nic->eeprom_wc) - return -EINVAL; - - for (addr = start; addr < start + count; addr++) - e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); - - /* The checksum, stored in the last word, is calculated such that - * the sum of words should be 0xBABA */ - for (addr = 0; addr < nic->eeprom_wc - 1; addr++) - checksum += le16_to_cpu(nic->eeprom[addr]); - nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); - e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, - nic->eeprom[nic->eeprom_wc - 1]); - - return 0; -} - -#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ -#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) -{ - unsigned long flags; - unsigned int i; - int err = 0; - - spin_lock_irqsave(&nic->cmd_lock, flags); - - /* Previous command is accepted when SCB clears */ - for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { - if (likely(!ioread8(&nic->csr->scb.cmd_lo))) - break; - cpu_relax(); - if (unlikely(i > E100_WAIT_SCB_FAST)) - udelay(5); - } - if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { - err = -EAGAIN; - goto err_unlock; - } - - if (unlikely(cmd != cuc_resume)) - iowrite32(dma_addr, &nic->csr->scb.gen_ptr); - iowrite8(cmd, &nic->csr->scb.cmd_lo); - -err_unlock: - spin_unlock_irqrestore(&nic->cmd_lock, flags); - - return err; -} - -static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, - void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) -{ - struct cb *cb; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&nic->cb_lock, flags); - - if (unlikely(!nic->cbs_avail)) { - err = -ENOMEM; - goto err_unlock; - } - - cb = nic->cb_to_use; - nic->cb_to_use = cb->next; - nic->cbs_avail--; - cb->skb = skb; - - if (unlikely(!nic->cbs_avail)) - err = -ENOSPC; - - cb_prepare(nic, cb, skb); - - /* Order is important otherwise we'll be in a race with h/w: - * set S-bit in current first, then clear S-bit in previous. */ - cb->command |= cpu_to_le16(cb_s); - wmb(); - cb->prev->command &= cpu_to_le16(~cb_s); - - while (nic->cb_to_send != nic->cb_to_use) { - if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, - nic->cb_to_send->dma_addr))) { - /* Ok, here's where things get sticky. It's - * possible that we can't schedule the command - * because the controller is too busy, so - * let's just queue the command and try again - * when another command is scheduled. */ - if (err == -ENOSPC) { - //request a reset - schedule_work(&nic->tx_timeout_task); - } - break; - } else { - nic->cuc_cmd = cuc_resume; - nic->cb_to_send = nic->cb_to_send->next; - } - } - -err_unlock: - spin_unlock_irqrestore(&nic->cb_lock, flags); - - return err; -} - -static int mdio_read(struct net_device *netdev, int addr, int reg) -{ - struct nic *nic = netdev_priv(netdev); - return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); -} - -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) -{ - struct nic *nic = netdev_priv(netdev); - - nic->mdio_ctrl(nic, addr, mdi_write, reg, data); -} - -/* the standard mdio_ctrl() function for usual MII-compliant hardware */ -static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) -{ - u32 data_out = 0; - unsigned int i; - unsigned long flags; - - - /* - * Stratus87247: we shouldn't be writing the MDI control - * register until the Ready bit shows True. Also, since - * manipulation of the MDI control registers is a multi-step - * procedure it should be done under lock. - */ - spin_lock_irqsave(&nic->mdio_lock, flags); - for (i = 100; i; --i) { - if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) - break; - udelay(20); - } - if (unlikely(!i)) { - netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n"); - spin_unlock_irqrestore(&nic->mdio_lock, flags); - return 0; /* No way to indicate timeout error */ - } - iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - - for (i = 0; i < 100; i++) { - udelay(20); - if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) - break; - } - spin_unlock_irqrestore(&nic->mdio_lock, flags); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data, data_out); - return (u16)data_out; -} - -/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ -static u16 mdio_ctrl_phy_82552_v(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - if ((reg == MII_BMCR) && (dir == mdi_write)) { - if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { - u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, - MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; - } - } - return mdio_ctrl_hw(nic, addr, dir, reg, data); -} - -/* Fully software-emulated mdio_ctrl() function for cards without - * MII-compliant PHYs. - * For now, this is mainly geared towards 80c24 support; in case of further - * requirements for other types (i82503, ...?) either extend this mechanism - * or split it, whichever is cleaner. - */ -static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, - u32 addr, - u32 dir, - u32 reg, - u16 data) -{ - /* might need to allocate a netdev_priv'ed register array eventually - * to be able to record state changes, but for now - * some fully hardcoded register handling ought to be ok I guess. */ - - if (dir == mdi_read) { - switch (reg) { - case MII_BMCR: - /* Auto-negotiation, right? */ - return BMCR_ANENABLE | - BMCR_FULLDPLX; - case MII_BMSR: - return BMSR_LSTATUS /* for mii_link_ok() */ | - BMSR_ANEGCAPABLE | - BMSR_10FULL; - case MII_ADVERTISE: - /* 80c24 is a "combo card" PHY, right? */ - return ADVERTISE_10HALF | - ADVERTISE_10FULL; - default: - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data); - return 0xFFFF; - } - } else { - switch (reg) { - default: - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", - dir == mdi_read ? "READ" : "WRITE", - addr, reg, data); - return 0xFFFF; - } - } -} -static inline int e100_phy_supports_mii(struct nic *nic) -{ - /* for now, just check it by comparing whether we - are using MII software emulation. - */ - return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); -} - -static void e100_get_defaults(struct nic *nic) -{ - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - - /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; - if (nic->mac == mac_unknown) - nic->mac = mac_82557_D100_A; - - nic->params.rfds = rfds; - nic->params.cbs = cbs; - - /* Quadwords to DMA into FIFO before starting frame transmit */ - nic->tx_threshold = 0xE0; - - /* no interrupt for every tx completion, delay = 256us if not 557 */ - nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); - - /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); - nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - - /* MII setup */ - nic->mii.phy_id_mask = 0x1F; - nic->mii.reg_num_mask = 0x1F; - nic->mii.dev = nic->netdev; - nic->mii.mdio_read = mdio_read; - nic->mii.mdio_write = mdio_write; -} - -static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct config *config = &cb->u.config; - u8 *c = (u8 *)config; - - cb->command = cpu_to_le16(cb_config); - - memset(config, 0, sizeof(struct config)); - - config->byte_count = 0x16; /* bytes in this struct */ - config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ - config->direct_rx_dma = 0x1; /* reserved */ - config->standard_tcb = 0x1; /* 1=standard, 0=extended */ - config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ - config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ - config->tx_underrun_retry = 0x3; /* # of underrun retries */ - if (e100_phy_supports_mii(nic)) - config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ - config->pad10 = 0x6; - config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ - config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ - config->ifs = 0x6; /* x16 = inter frame spacing */ - config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ - config->pad15_1 = 0x1; - config->pad15_2 = 0x1; - config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ - config->fc_delay_hi = 0x40; /* time delay for fc frame */ - config->tx_padding = 0x1; /* 1=pad short frames */ - config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ - config->pad18 = 0x1; - config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ - config->pad20_1 = 0x1F; - config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ - config->pad21_1 = 0x5; - - config->adaptive_ifs = nic->adaptive_ifs; - config->loopback = nic->loopback; - - if (nic->mii.force_media && nic->mii.full_duplex) - config->full_duplex_force = 0x1; /* 1=force, 0=auto */ - - if (nic->flags & promiscuous || nic->loopback) { - config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ - config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ - config->promiscuous_mode = 0x1; /* 1=on, 0=off */ - } - - if (nic->flags & multicast_all) - config->multicast_all = 0x1; /* 1=accept, 0=no */ - - /* disable WoL when up */ - if (netif_running(nic->netdev) || !(nic->flags & wol_magic)) - config->magic_packet_disable = 0x1; /* 1=off, 0=on */ - - if (nic->mac >= mac_82558_D101_A4) { - config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ - config->mwi_enable = 0x1; /* 1=enable, 0=disable */ - config->standard_tcb = 0x0; /* 1=standard, 0=extended */ - config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if (nic->mac >= mac_82559_D101M) { - config->tno_intr = 0x1; /* TCO stats enable */ - /* Enable TCO in extended config */ - if (nic->mac >= mac_82551_10) { - config->byte_count = 0x20; /* extended bytes */ - config->rx_d102_mode = 0x1; /* GMRC for TCO */ - } - } else { - config->standard_stat_counter = 0x0; - } - } - - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); -} - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change the algorithm. -* -* INTDELAY - This loads the dead-man timer with its initial value. -* When this timer expires the interrupt is asserted, and the -* timer is reset each time a new packet is received. (see -* BUNDLEMAX below to set the limit on number of chained packets) -* The current default is 0x600 or 1536. Experiments show that -* the value should probably stay within the 0x200 - 0x1000. -* -* BUNDLEMAX - -* This sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* BUNDLESMALL - -* This contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -/* if you wish to disable the ucode functionality, while maintaining the - * workarounds it provides, set the following defines to: - * BUNDLESMALL 0 - * BUNDLEMAX 1 - * INTDELAY 1 - */ -#define BUNDLESMALL 1 -#define BUNDLEMAX (u16)6 -#define INTDELAY (u16)1536 /* 0x600 */ - -/* Initialize firmware */ -static const struct firmware *e100_request_firmware(struct nic *nic) -{ - const char *fw_name; - const struct firmware *fw = nic->fw; - u8 timer, bundle, min_size; - int err = 0; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return NULL; - - /* Search for ucode match against h/w revision */ - if (nic->mac == mac_82559_D101M) - fw_name = FIRMWARE_D101M; - else if (nic->mac == mac_82559_D101S) - fw_name = FIRMWARE_D101S; - else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) - fw_name = FIRMWARE_D102E; - else /* No ucode on other devices */ - return NULL; - - /* If the firmware has not previously been loaded, request a pointer - * to it. If it was previously loaded, we are reinitializing the - * adapter, possibly in a resume from hibernate, in which case - * request_firmware() cannot be used. - */ - if (!fw) - err = request_firmware(&fw, fw_name, &nic->pdev->dev); - - if (err) { - netif_err(nic, probe, nic->netdev, - "Failed to load firmware \"%s\": %d\n", - fw_name, err); - return ERR_PTR(err); - } - - /* Firmware should be precisely UCODE_SIZE (words) plus three bytes - indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ - if (fw->size != UCODE_SIZE * 4 + 3) { - netif_err(nic, probe, nic->netdev, - "Firmware \"%s\" has wrong size %zu\n", - fw_name, fw->size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || - min_size >= UCODE_SIZE) { - netif_err(nic, probe, nic->netdev, - "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", - fw_name, timer, bundle, min_size); - release_firmware(fw); - return ERR_PTR(-EINVAL); - } - - /* OK, firmware is validated and ready to use. Save a pointer - * to it in the nic */ - nic->fw = fw; - return fw; -} - -static void e100_setup_ucode(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - const struct firmware *fw = (void *)skb; - u8 timer, bundle, min_size; - - /* It's not a real skb; we just abused the fact that e100_exec_cb - will pass it through to here... */ - cb->skb = NULL; - - /* firmware is stored as little endian already */ - memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); - - /* Read timer, bundle and min_size from end of firmware blob */ - timer = fw->data[UCODE_SIZE * 4]; - bundle = fw->data[UCODE_SIZE * 4 + 1]; - min_size = fw->data[UCODE_SIZE * 4 + 2]; - - /* Insert user-tunable settings in cb->u.ucode */ - cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); - cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); - cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); - cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); - - cb->command = cpu_to_le16(cb_ucode | cb_el); -} - -static inline int e100_load_ucode_wait(struct nic *nic) -{ - const struct firmware *fw; - int err = 0, counter = 50; - struct cb *cb = nic->cb_to_clean; - - fw = e100_request_firmware(nic); - /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); - - if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) - netif_err(nic, probe, nic->netdev, - "ucode cmd failed with error %d\n", err); - - /* must restart cuc */ - nic->cuc_cmd = cuc_start; - - /* wait for completion */ - e100_write_flush(nic); - udelay(10); - - /* wait for possibly (ouch) 500ms */ - while (!(cb->status & cpu_to_le16(cb_complete))) { - msleep(10); - if (!--counter) break; - } - - /* ack any interrupts, something could have been set */ - iowrite8(~0, &nic->csr->scb.stat_ack); - - /* if the command failed, or is not OK, notify and return */ - if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { - netif_err(nic, probe, nic->netdev, "ucode load failed\n"); - err = -EPERM; - } - - return err; -} - -static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_iaaddr); - memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); -} - -static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - cb->command = cpu_to_le16(cb_dump); - cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + - offsetof(struct mem, dump_buf)); -} - -static int e100_phy_check_without_mii(struct nic *nic) -{ - u8 phy_type; - int without_mii; - - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; - - switch (phy_type) { - case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ - case I82503: /* Non-MII PHY; UNTESTED! */ - case S80C24: /* Non-MII PHY; tested and working */ - /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - netif_info(nic, probe, nic->netdev, - "found MII-less i82503 or 80c24 or other PHY\n"); - - nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; - nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ - - /* these might be needed for certain MII-less cards... - * nic->flags |= ich; - * nic->flags |= ich_10h_workaround; */ - - without_mii = 1; - break; - default: - without_mii = 0; - break; - } - return without_mii; -} - -#define NCONFIG_AUTO_SWITCH 0x0080 -#define MII_NSC_CONG MII_RESV1 -#define NSC_CONG_ENABLE 0x0100 -#define NSC_CONG_TXREADY 0x0400 -#define ADVERTISE_FC_SUPPORTED 0x0400 -static int e100_phy_init(struct nic *nic) -{ - struct net_device *netdev = nic->netdev; - u32 addr; - u16 bmcr, stat, id_lo, id_hi, cong; - - /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ - for (addr = 0; addr < 32; addr++) { - nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); - if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) - break; - } - if (addr == 32) { - /* uhoh, no PHY detected: check whether we seem to be some - * weird, rare variant which is *known* to not have any MII. - * But do this AFTER MII checking only, since this does - * lookup of EEPROM values which may easily be unreliable. */ - if (e100_phy_check_without_mii(nic)) - return 0; /* simply return and hope for the best */ - else { - /* for unknown cases log a fatal error */ - netif_err(nic, hw, nic->netdev, - "Failed to locate any known PHY, aborting\n"); - return -EAGAIN; - } - } else - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "phy_addr = %d\n", nic->mii.phy_id); - - /* Get phy ID */ - id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); - id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); - nic->phy = (u32)id_hi << 16 | (u32)id_lo; - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "phy ID = 0x%08X\n", nic->phy); - - /* Select the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else if (nic->phy != phy_82552_v) { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - /* - * Workaround for 82552: - * Clear the ISOLATE bit on selected phy_id last (mirrored on all - * other phy_id's) using bmcr value from addr discovery loop above. - */ - if (nic->phy == phy_82552_v) - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - - /* Handle National tx phys */ -#define NCS_PHY_MODEL_MASK 0xFFF0FFFF - if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { - /* Disable congestion control */ - cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); - cong |= NSC_CONG_TXREADY; - cong &= ~NSC_CONG_ENABLE; - mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); - } - - if (nic->phy == phy_82552_v) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* assign special tweaked mdio_ctrl() function */ - nic->mdio_ctrl = mdio_ctrl_phy_82552_v; - - /* Workaround Si not advertising flow-control during autoneg */ - advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); - - /* Reset for the above changes to take effect */ - bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); - bmcr |= BMCR_RESET; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { - /* enable/disable MDI/MDI-X auto-switching. */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); - } - - return 0; -} - -static int e100_hw_init(struct nic *nic) -{ - int err; - - e100_hw_reset(nic); - - netif_err(nic, hw, nic->netdev, "e100_hw_init\n"); - if (!in_interrupt() && (err = e100_self_test(nic))) - return err; - - if ((err = e100_phy_init(nic))) - return err; - if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) - return err; - if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) - return err; - if ((err = e100_load_ucode_wait(nic))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_configure))) - return err; - if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_addr, - nic->dma_addr + offsetof(struct mem, stats)))) - return err; - if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) - return err; - - e100_disable_irq(nic); - - return 0; -} - -static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) -{ - struct net_device *netdev = nic->netdev; - struct netdev_hw_addr *ha; - u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS); - - cb->command = cpu_to_le16(cb_multi); - cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - i = 0; - netdev_for_each_mc_addr(ha, netdev) { - if (i == count) - break; - memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr, - ETH_ALEN); - } -} - -static void e100_set_multicast_list(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - netif_printk(nic, hw, KERN_DEBUG, nic->netdev, - "mc_count=%d, flags=0x%04X\n", - netdev_mc_count(netdev), netdev->flags); - - if (netdev->flags & IFF_PROMISC) - nic->flags |= promiscuous; - else - nic->flags &= ~promiscuous; - - if (netdev->flags & IFF_ALLMULTI || - netdev_mc_count(netdev) > E100_MAX_MULTICAST_ADDRS) - nic->flags |= multicast_all; - else - nic->flags &= ~multicast_all; - - e100_exec_cb(nic, NULL, e100_configure); - e100_exec_cb(nic, NULL, e100_multi); -} - -static void e100_update_stats(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct net_device_stats *ns = &dev->stats; - struct stats *s = &nic->mem->stats; - __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : - (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : - &s->complete; - - /* Device's stats reporting may take several microseconds to - * complete, so we're always waiting for results of the - * previous command. */ - - if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { - *complete = 0; - nic->tx_frames = le32_to_cpu(s->tx_good_frames); - nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); - ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); - ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); - ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); - ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); - ns->collisions += nic->tx_collisions; - ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + - le32_to_cpu(s->tx_lost_crs); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + - nic->rx_over_length_errors; - ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); - ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); - ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); - ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); - ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + - le32_to_cpu(s->rx_alignment_errors) + - le32_to_cpu(s->rx_short_frame_errors) + - le32_to_cpu(s->rx_cdt_errors); - nic->tx_deferred += le32_to_cpu(s->tx_deferred); - nic->tx_single_collisions += - le32_to_cpu(s->tx_single_collisions); - nic->tx_multiple_collisions += - le32_to_cpu(s->tx_multiple_collisions); - if (nic->mac >= mac_82558_D101_A4) { - nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); - nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); - nic->rx_fc_unsupported += - le32_to_cpu(s->fc_rcv_unsupported); - if (nic->mac >= mac_82559_D101M) { - nic->tx_tco_frames += - le16_to_cpu(s->xmt_tco_frames); - nic->rx_tco_frames += - le16_to_cpu(s->rcv_tco_frames); - } - } - } - - - if (e100_exec_cmd(nic, cuc_dump_reset, 0)) - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "exec cuc_dump_reset failed\n"); -} - -static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) -{ - /* Adjust inter-frame-spacing (IFS) between two transmits if - * we're getting collisions on a half-duplex connection. */ - - if (duplex == DUPLEX_HALF) { - u32 prev = nic->adaptive_ifs; - u32 min_frames = (speed == SPEED_100) ? 1000 : 100; - - if ((nic->tx_frames / 32 < nic->tx_collisions) && - (nic->tx_frames > min_frames)) { - if (nic->adaptive_ifs < 60) - nic->adaptive_ifs += 5; - } else if (nic->tx_frames < min_frames) { - if (nic->adaptive_ifs >= 5) - nic->adaptive_ifs -= 5; - } - if (nic->adaptive_ifs != prev) - e100_exec_cb(nic, NULL, e100_configure); - } -} - -static void e100_watchdog(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; - - netif_printk(nic, timer, KERN_DEBUG, nic->netdev, - "right now = %ld\n", jiffies); - - /* mii library handles link maintenance tasks */ - - mii_ethtool_gset(&nic->mii, &cmd); - - if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { - netdev_info(nic->netdev, "NIC Link is Up %u Mbps %s Duplex\n", - cmd.speed == SPEED_100 ? 100 : 10, - cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); - } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { - netdev_info(nic->netdev, "NIC Link is Down\n"); - } - - mii_check_link(&nic->mii); - - /* Software generated interrupt to recover from (rare) Rx - * allocation failure. - * Unfortunately have to use a spinlock to not re-enable interrupts - * accidentally, due to hardware that shares a register between the - * interrupt mask bit and the SW Interrupt generation bit */ - spin_lock_irq(&nic->cmd_lock); - iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - e100_write_flush(nic); - spin_unlock_irq(&nic->cmd_lock); - - e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); - - if (nic->mac <= mac_82557_D100_C) - /* Issue a multicast command to workaround a 557 lock up */ - e100_set_multicast_list(nic->netdev); - - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) - /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ - nic->flags |= ich_10h_workaround; - else - nic->flags &= ~ich_10h_workaround; - - mod_timer(&nic->watchdog, - round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); -} - -static void e100_xmit_prepare(struct nic *nic, struct cb *cb, - struct sk_buff *skb) -{ - cb->command = nic->tx_command; - /* interrupt every 16 packets regardless of delay */ - if ((nic->cbs_avail & ~15) == nic->cbs_avail) - cb->command |= cpu_to_le16(cb_i); - cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); - cb->u.tcb.tcb_byte_count = 0; - cb->u.tcb.threshold = nic->tx_threshold; - cb->u.tcb.tbd_count = 1; - cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE)); - /* check for mapping failure? */ - cb->u.tcb.tbd.size = cpu_to_le16(skb->len); -} - -static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - if (nic->flags & ich_10h_workaround) { - /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. - Issue a NOP command followed by a 1us delay before - issuing the Tx command. */ - if (e100_exec_cmd(nic, cuc_nop, 0)) - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "exec cuc_nop failed\n"); - udelay(1); - } - - err = e100_exec_cb(nic, skb, e100_xmit_prepare); - - switch (err) { - case -ENOSPC: - /* We queued the skb, but now we're out of space. */ - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "No space for CB\n"); - netif_stop_queue(netdev); - break; - case -ENOMEM: - /* This is a hard error - log it. */ - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "Out of Tx resources, returning skb\n"); - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - return NETDEV_TX_OK; -} - -static int e100_tx_clean(struct nic *nic) -{ - struct net_device *dev = nic->netdev; - struct cb *cb; - int tx_cleaned = 0; - - spin_lock(&nic->cb_lock); - - /* Clean CBs marked complete */ - for (cb = nic->cb_to_clean; - cb->status & cpu_to_le16(cb_complete); - cb = nic->cb_to_clean = cb->next) { - rmb(); /* read skb after status */ - netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev, - "cb[%d]->status = 0x%04X\n", - (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), - cb->status); - - if (likely(cb->skb != NULL)) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += cb->skb->len; - - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb_any(cb->skb); - cb->skb = NULL; - tx_cleaned = 1; - } - cb->status = 0; - nic->cbs_avail++; - } - - spin_unlock(&nic->cb_lock); - - /* Recover from running out of Tx resources in xmit_frame */ - if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) - netif_wake_queue(nic->netdev); - - return tx_cleaned; -} - -static void e100_clean_cbs(struct nic *nic) -{ - if (nic->cbs) { - while (nic->cbs_avail != nic->params.cbs.count) { - struct cb *cb = nic->cb_to_clean; - if (cb->skb) { - pci_unmap_single(nic->pdev, - le32_to_cpu(cb->u.tcb.tbd.buf_addr), - le16_to_cpu(cb->u.tcb.tbd.size), - PCI_DMA_TODEVICE); - dev_kfree_skb(cb->skb); - } - nic->cb_to_clean = nic->cb_to_clean->next; - nic->cbs_avail++; - } - pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); - nic->cbs = NULL; - nic->cbs_avail = 0; - } - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = - nic->cbs; -} - -static int e100_alloc_cbs(struct nic *nic) -{ - struct cb *cb; - unsigned int i, count = nic->params.cbs.count; - - nic->cuc_cmd = cuc_start; - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; - nic->cbs_avail = 0; - - nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, - &nic->cbs_dma_addr); - if (!nic->cbs) - return -ENOMEM; - memset(nic->cbs, 0, count * sizeof(struct cb)); - - for (cb = nic->cbs, i = 0; i < count; cb++, i++) { - cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; - cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; - - cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); - cb->link = cpu_to_le32(nic->cbs_dma_addr + - ((i+1) % count) * sizeof(struct cb)); - } - - nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; - nic->cbs_avail = count; - - return 0; -} - -static inline void e100_start_receiver(struct nic *nic, struct rx *rx) -{ - if (!nic->rxs) return; - if (RU_SUSPENDED != nic->ru_running) return; - - /* handle init time starts */ - if (!rx) rx = nic->rxs; - - /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if (rx->skb) { - e100_exec_cmd(nic, ruc_start, rx->dma_addr); - nic->ru_running = RU_RUNNING; - } -} - -#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) -{ - if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) - return -ENOMEM; - - /* Init, and map the RFD. */ - skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); - rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { - dev_kfree_skb_any(rx->skb); - rx->skb = NULL; - rx->dma_addr = 0; - return -ENOMEM; - } - - /* Link the RFD to end of RFA by linking previous RFD to - * this one. We are safe to touch the previous RFD because - * it is protected by the before last buffer's el bit being set */ - if (rx->prev->skb) { - struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; - put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - } - - return 0; -} - -static int e100_rx_indicate(struct nic *nic, struct rx *rx, - unsigned int *work_done, unsigned int work_to_do) -{ - struct net_device *dev = nic->netdev; - struct sk_buff *skb = rx->skb; - struct rfd *rfd = (struct rfd *)skb->data; - u16 rfd_status, actual_size; - - if (unlikely(work_done && *work_done >= work_to_do)) - return -EAGAIN; - - /* Need to sync before taking a peek at cb_complete bit */ - pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - rfd_status = le16_to_cpu(rfd->status); - - netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev, - "status=0x%04X\n", rfd_status); - rmb(); /* read size after status bit */ - - /* If data isn't ready, nothing to indicate */ - if (unlikely(!(rfd_status & cb_complete))) { - /* If the next buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling - * interrupts */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), - PCI_DMA_FROMDEVICE); - return -ENODATA; - } - - /* Get actual data size */ - actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; - if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) - actual_size = RFD_BUF_LEN - sizeof(struct rfd); - - /* Get data */ - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - /* If this buffer has the el bit, but we think the receiver - * is still running, check to see if it really stopped while - * we had interrupts off. - * This allows for a fast restart without re-enabling interrupts. - * This can happen when the RU sees the size change but also sees - * the el bit set. */ - if ((le16_to_cpu(rfd->command) & cb_el) && - (RU_RUNNING == nic->ru_running)) { - - if (ioread8(&nic->csr->scb.status) & rus_no_res) - nic->ru_running = RU_SUSPENDED; - } - - /* Pull off the RFD and put the actual data (minus eth hdr) */ - skb_reserve(skb, sizeof(struct rfd)); - skb_put(skb, actual_size); - skb->protocol = eth_type_trans(skb, nic->netdev); - - if (unlikely(!(rfd_status & cb_ok))) { - /* Don't indicate if hardware indicates errors */ - dev_kfree_skb_any(skb); - } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { - /* Don't indicate oversized frames */ - nic->rx_over_length_errors++; - dev_kfree_skb_any(skb); - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += actual_size; - netif_receive_skb(skb); - if (work_done) - (*work_done)++; - } - - rx->skb = NULL; - - return 0; -} - -static void e100_rx_clean(struct nic *nic, unsigned int *work_done, - unsigned int work_to_do) -{ - struct rx *rx; - int restart_required = 0, err = 0; - struct rx *old_before_last_rx, *new_before_last_rx; - struct rfd *old_before_last_rfd, *new_before_last_rfd; - - /* Indicate newly arrived packets */ - for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - err = e100_rx_indicate(nic, rx, work_done, work_to_do); - /* Hit quota or no more to clean */ - if (-EAGAIN == err || -ENODATA == err) - break; - } - - - /* On EAGAIN, hit quota so have more work to do, restart once - * cleanup is complete. - * Else, are we already rnr? then pay attention!!! this ensures that - * the state machine progression never allows a start with a - * partially cleaned list, avoiding a race between hardware - * and rx_to_clean when in NAPI mode */ - if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) - restart_required = 1; - - old_before_last_rx = nic->rx_to_use->prev->prev; - old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - - /* Alloc new skbs to refill list */ - for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { - if (unlikely(e100_rx_alloc_skb(nic, rx))) - break; /* Better luck next time (see watchdog) */ - } - - new_before_last_rx = nic->rx_to_use->prev->prev; - if (new_before_last_rx != old_before_last_rx) { - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer - * without worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this - * buffer. - * When the hardware hits the before last buffer with el-bit - * and size of 0, it will RNR interrupt, the RUS will go into - * the No Resources state. It will not complete nor write to - * this buffer. */ - new_before_last_rfd = - (struct rfd *)new_before_last_rx->skb->data; - new_before_last_rfd->size = 0; - new_before_last_rfd->command |= cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - - /* Now that we have a new stopping point, we can clear the old - * stopping point. We must sync twice to get the proper - * ordering on the hardware side of things. */ - old_before_last_rfd->command &= ~cpu_to_le16(cb_el); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); - pci_dma_sync_single_for_device(nic->pdev, - old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); - } - - if (restart_required) { - // ack the rnr? - iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); - e100_start_receiver(nic, nic->rx_to_clean); - if (work_done) - (*work_done)++; - } -} - -static void e100_rx_clean_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - - nic->ru_running = RU_UNINITIALIZED; - - if (nic->rxs) { - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - if (rx->skb) { - pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - dev_kfree_skb(rx->skb); - } - } - kfree(nic->rxs); - nic->rxs = NULL; - } - - nic->rx_to_use = nic->rx_to_clean = NULL; -} - -static int e100_rx_alloc_list(struct nic *nic) -{ - struct rx *rx; - unsigned int i, count = nic->params.rfds.count; - struct rfd *before_last; - - nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = RU_UNINITIALIZED; - - if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) - return -ENOMEM; - - for (rx = nic->rxs, i = 0; i < count; rx++, i++) { - rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; - rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; - if (e100_rx_alloc_skb(nic, rx)) { - e100_rx_clean_list(nic); - return -ENOMEM; - } - } - /* Set the el-bit on the buffer that is before the last buffer. - * This lets us update the next pointer on the last buffer without - * worrying about hardware touching it. - * We set the size to 0 to prevent hardware from touching this buffer. - * When the hardware hits the before last buffer with el-bit and size - * of 0, it will RNR interrupt, the RU will go into the No Resources - * state. It will not complete nor write to this buffer. */ - rx = nic->rxs->prev->prev; - before_last = (struct rfd *)rx->skb->data; - before_last->command |= cpu_to_le16(cb_el); - before_last->size = 0; - pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); - - nic->rx_to_use = nic->rx_to_clean = nic->rxs; - nic->ru_running = RU_SUSPENDED; - - return 0; -} - -static irqreturn_t e100_intr(int irq, void *dev_id) -{ - struct net_device *netdev = dev_id; - struct nic *nic = netdev_priv(netdev); - u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); - - netif_printk(nic, intr, KERN_DEBUG, nic->netdev, - "stat_ack = 0x%02X\n", stat_ack); - - if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ - stat_ack == stat_ack_not_present) /* Hardware is ejected */ - return IRQ_NONE; - - /* Ack interrupt(s) */ - iowrite8(stat_ack, &nic->csr->scb.stat_ack); - - /* We hit Receive No Resource (RNR); restart RU after cleaning */ - if (stat_ack & stat_ack_rnr) - nic->ru_running = RU_SUSPENDED; - - if (likely(napi_schedule_prep(&nic->napi))) { - e100_disable_irq(nic); - __napi_schedule(&nic->napi); - } - - return IRQ_HANDLED; -} - -static int e100_poll(struct napi_struct *napi, int budget) -{ - struct nic *nic = container_of(napi, struct nic, napi); - unsigned int work_done = 0; - - e100_rx_clean(nic, &work_done, budget); - e100_tx_clean(nic); - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - napi_complete(napi); - e100_enable_irq(nic); - } - - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - e100_disable_irq(nic); - e100_intr(nic->pdev->irq, netdev); - e100_tx_clean(nic); - e100_enable_irq(nic); -} -#endif - -static int e100_set_mac_address(struct net_device *netdev, void *p) -{ - struct nic *nic = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - e100_exec_cb(nic, NULL, e100_setup_iaaddr); - - return 0; -} - -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) - return -EINVAL; - netdev->mtu = new_mtu; - return 0; -} - -static int e100_asf(struct nic *nic) -{ - /* ASF can be enabled from eeprom */ - return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE); -} - -static int e100_up(struct nic *nic) -{ - int err; - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_rx_clean_list; - if ((err = e100_hw_init(nic))) - goto err_clean_cbs; - e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, NULL); - mod_timer(&nic->watchdog, jiffies); - if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, - nic->netdev->name, nic->netdev))) - goto err_no_irq; - netif_wake_queue(nic->netdev); - napi_enable(&nic->napi); - /* enable ints _after_ enabling poll, preventing a race between - * disable ints+schedule */ - e100_enable_irq(nic); - return 0; - -err_no_irq: - del_timer_sync(&nic->watchdog); -err_clean_cbs: - e100_clean_cbs(nic); -err_rx_clean_list: - e100_rx_clean_list(nic); - return err; -} - -static void e100_down(struct nic *nic) -{ - /* wait here for poll to complete */ - napi_disable(&nic->napi); - netif_stop_queue(nic->netdev); - e100_hw_reset(nic); - free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); - netif_carrier_off(nic->netdev); - e100_clean_cbs(nic); - e100_rx_clean_list(nic); -} - -static void e100_tx_timeout(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - - /* Reset outside of interrupt context, to avoid request_irq - * in interrupt context */ - schedule_work(&nic->tx_timeout_task); -} - -static void e100_tx_timeout_task(struct work_struct *work) -{ - struct nic *nic = container_of(work, struct nic, tx_timeout_task); - struct net_device *netdev = nic->netdev; - - netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, - "scb.status=0x%02X\n", ioread8(&nic->csr->scb.status)); - - rtnl_lock(); - if (netif_running(netdev)) { - e100_down(netdev_priv(netdev)); - e100_up(netdev_priv(netdev)); - } - rtnl_unlock(); -} - -static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) -{ - int err; - struct sk_buff *skb; - - /* Use driver resources to perform internal MAC or PHY - * loopback test. A single packet is prepared and transmitted - * in loopback mode, and the test passes if the received - * packet compares byte-for-byte to the transmitted packet. */ - - if ((err = e100_rx_alloc_list(nic))) - return err; - if ((err = e100_alloc_cbs(nic))) - goto err_clean_rx; - - /* ICH PHY loopback is broken so do MAC loopback instead */ - if (nic->flags & ich && loopback_mode == lb_phy) - loopback_mode = lb_mac; - - nic->loopback = loopback_mode; - if ((err = e100_hw_init(nic))) - goto err_loopback_none; - - if (loopback_mode == lb_phy) - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, - BMCR_LOOPBACK); - - e100_start_receiver(nic, NULL); - - if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { - err = -ENOMEM; - goto err_loopback_none; - } - skb_put(skb, ETH_DATA_LEN); - memset(skb->data, 0xFF, ETH_DATA_LEN); - e100_xmit_frame(skb, nic->netdev); - - msleep(10); - - pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); - - if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), - skb->data, ETH_DATA_LEN)) - err = -EAGAIN; - -err_loopback_none: - mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); - nic->loopback = lb_none; - e100_clean_cbs(nic); - e100_hw_reset(nic); -err_clean_rx: - e100_rx_clean_list(nic); - return err; -} - -#define MII_LED_CONTROL 0x1B -#define E100_82552_LED_OVERRIDE 0x19 -#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ -#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} - -static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - return mii_ethtool_gset(&nic->mii, cmd); -} - -static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) -{ - struct nic *nic = netdev_priv(netdev); - int err; - - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); - err = mii_ethtool_sset(&nic->mii, cmd); - e100_exec_cb(nic, NULL, e100_configure); - - return err; -} - -static void e100_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) -{ - struct nic *nic = netdev_priv(netdev); - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, pci_name(nic->pdev)); -} - -#define E100_PHY_REGS 0x1C -static int e100_get_regs_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); -} - -static void e100_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct nic *nic = netdev_priv(netdev); - u32 *buff = p; - int i; - - regs->version = (1 << 24) | nic->pdev->revision; - buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | - ioread8(&nic->csr->scb.cmd_lo) << 16 | - ioread16(&nic->csr->scb.status); - for (i = E100_PHY_REGS; i >= 0; i--) - buff[1 + E100_PHY_REGS - i] = - mdio_read(netdev, nic->mii.phy_id, i); - memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); - e100_exec_cb(nic, NULL, e100_dump); - msleep(10); - memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, - sizeof(nic->mem->dump_buf)); -} - -static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; - wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; -} - -static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct nic *nic = netdev_priv(netdev); - - if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || - !device_can_wakeup(&nic->pdev->dev)) - return -EOPNOTSUPP; - - if (wol->wolopts) - nic->flags |= wol_magic; - else - nic->flags &= ~wol_magic; - - device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); - - e100_exec_cb(nic, NULL, e100_configure); - - return 0; -} - -static u32 e100_get_msglevel(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->msg_enable; -} - -static void e100_set_msglevel(struct net_device *netdev, u32 value) -{ - struct nic *nic = netdev_priv(netdev); - nic->msg_enable = value; -} - -static int e100_nway_reset(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_nway_restart(&nic->mii); -} - -static u32 e100_get_link(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return mii_link_ok(&nic->mii); -} - -static int e100_get_eeprom_len(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - return nic->eeprom_wc << 1; -} - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - eeprom->magic = E100_EEPROM_MAGIC; - memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); - - return 0; -} - -static int e100_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct nic *nic = netdev_priv(netdev); - - if (eeprom->magic != E100_EEPROM_MAGIC) - return -EINVAL; - - memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); - - return e100_eeprom_save(nic, eeprom->offset >> 1, - (eeprom->len >> 1) + 1); -} - -static void e100_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - ring->rx_max_pending = rfds->max; - ring->tx_max_pending = cbs->max; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = rfds->count; - ring->tx_pending = cbs->count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -static int e100_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct nic *nic = netdev_priv(netdev); - struct param_range *rfds = &nic->params.rfds; - struct param_range *cbs = &nic->params.cbs; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - if (netif_running(netdev)) - e100_down(nic); - rfds->count = max(ring->rx_pending, rfds->min); - rfds->count = min(rfds->count, rfds->max); - cbs->count = max(ring->tx_pending, cbs->min); - cbs->count = min(cbs->count, cbs->max); - netif_info(nic, drv, nic->netdev, "Ring Param settings: rx: %d, tx %d\n", - rfds->count, cbs->count); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} - -static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", -}; -#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) - -static void e100_diag_test(struct net_device *netdev, - struct ethtool_test *test, u64 *data) -{ - struct ethtool_cmd cmd; - struct nic *nic = netdev_priv(netdev); - int i, err; - - memset(data, 0, E100_TEST_LEN * sizeof(u64)); - data[0] = !mii_link_ok(&nic->mii); - data[1] = e100_eeprom_load(nic); - if (test->flags & ETH_TEST_FL_OFFLINE) { - - /* save speed, duplex & autoneg settings */ - err = mii_ethtool_gset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_down(nic); - data[2] = e100_self_test(nic); - data[3] = e100_loopback_test(nic, lb_mac); - data[4] = e100_loopback_test(nic, lb_phy); - - /* restore speed, duplex & autoneg settings */ - err = mii_ethtool_sset(&nic->mii, &cmd); - - if (netif_running(netdev)) - e100_up(nic); - } - for (i = 0; i < E100_TEST_LEN; i++) - test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; - - msleep_interruptible(4 * 1000); -} - -static int e100_phys_id(struct net_device *netdev, u32 data) -{ - struct nic *nic = netdev_priv(netdev); - u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; - - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); - - return 0; -} - -static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - /* device-specific stats */ - "tx_deferred", "tx_single_collisions", "tx_multi_collisions", - "tx_flow_control_pause", "rx_flow_control_pause", - "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", -}; -#define E100_NET_STATS_LEN 21 -#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) - -static int e100_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E100_TEST_LEN; - case ETH_SS_STATS: - return E100_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e100_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct nic *nic = netdev_priv(netdev); - int i; - - for (i = 0; i < E100_NET_STATS_LEN; i++) - data[i] = ((unsigned long *)&netdev->stats)[i]; - - data[i++] = nic->tx_deferred; - data[i++] = nic->tx_single_collisions; - data[i++] = nic->tx_multiple_collisions; - data[i++] = nic->tx_fc_pause; - data[i++] = nic->rx_fc_pause; - data[i++] = nic->rx_fc_unsupported; - data[i++] = nic->tx_tco_frames; - data[i++] = nic->rx_tco_frames; -} - -static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); - break; - case ETH_SS_STATS: - memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); - break; - } -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_settings = e100_get_settings, - .set_settings = e100_set_settings, - .get_drvinfo = e100_get_drvinfo, - .get_regs_len = e100_get_regs_len, - .get_regs = e100_get_regs, - .get_wol = e100_get_wol, - .set_wol = e100_set_wol, - .get_msglevel = e100_get_msglevel, - .set_msglevel = e100_set_msglevel, - .nway_reset = e100_nway_reset, - .get_link = e100_get_link, - .get_eeprom_len = e100_get_eeprom_len, - .get_eeprom = e100_get_eeprom, - .set_eeprom = e100_set_eeprom, - .get_ringparam = e100_get_ringparam, - .set_ringparam = e100_set_ringparam, - .self_test = e100_diag_test, - .get_strings = e100_get_strings, - .phys_id = e100_phys_id, - .get_ethtool_stats = e100_get_ethtool_stats, - .get_sset_count = e100_get_sset_count, -}; - -static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct nic *nic = netdev_priv(netdev); - - return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); -} - -static int e100_alloc(struct nic *nic) -{ - nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), - &nic->dma_addr); - return nic->mem ? 0 : -ENOMEM; -} - -static void e100_free(struct nic *nic) -{ - if (nic->mem) { - pci_free_consistent(nic->pdev, sizeof(struct mem), - nic->mem, nic->dma_addr); - nic->mem = NULL; - } -} - -static int e100_open(struct net_device *netdev) -{ - struct nic *nic = netdev_priv(netdev); - int err = 0; - - netif_carrier_off(netdev); - if ((err = e100_up(nic))) - netif_err(nic, ifup, nic->netdev, "Cannot open interface, aborting\n"); - return err; -} - -static int e100_close(struct net_device *netdev) -{ - e100_down(netdev_priv(netdev)); - return 0; -} - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_xmit_frame, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = e100_set_multicast_list, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_change_mtu = e100_change_mtu, - .ndo_do_ioctl = e100_do_ioctl, - .ndo_tx_timeout = e100_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct nic *nic; - int err; - - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - pr_err("Etherdev alloc failed, aborting\n"); - return -ENOMEM; - } - - netdev->netdev_ops = &e100_netdev_ops; - SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); - netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - nic = netdev_priv(netdev); - netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); - nic->netdev = netdev; - nic->pdev = pdev; - nic->msg_enable = (1 << debug) - 1; - nic->mdio_ctrl = mdio_ctrl_hw; - pci_set_drvdata(pdev, netdev); - - if ((err = pci_enable_device(pdev))) { - netif_err(nic, probe, nic->netdev, "Cannot enable PCI device, aborting\n"); - goto err_out_free_dev; - } - - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - netif_err(nic, probe, nic->netdev, "Cannot find proper PCI device base address, aborting\n"); - err = -ENODEV; - goto err_out_disable_pdev; - } - - if ((err = pci_request_regions(pdev, DRV_NAME))) { - netif_err(nic, probe, nic->netdev, "Cannot obtain PCI resources, aborting\n"); - goto err_out_disable_pdev; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - netif_err(nic, probe, nic->netdev, "No usable DMA configuration, aborting\n"); - goto err_out_free_res; - } - - SET_NETDEV_DEV(netdev, &pdev->dev); - - if (use_io) - netif_info(nic, probe, nic->netdev, "using i/o access mode\n"); - - nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); - if (!nic->csr) { - netif_err(nic, probe, nic->netdev, "Cannot map device registers, aborting\n"); - err = -ENOMEM; - goto err_out_free_res; - } - - if (ent->driver_data) - nic->flags |= ich; - else - nic->flags &= ~ich; - - e100_get_defaults(nic); - - /* locks must be initialized before calling hw_reset */ - spin_lock_init(&nic->cb_lock); - spin_lock_init(&nic->cmd_lock); - spin_lock_init(&nic->mdio_lock); - - /* Reset the device before pci_set_master() in case device is in some - * funky state and has an interrupt pending - hint: we don't have the - * interrupt handler registered yet. */ - e100_hw_reset(nic); - - pci_set_master(pdev); - - init_timer(&nic->watchdog); - nic->watchdog.function = e100_watchdog; - nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; - - INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); - - if ((err = e100_alloc(nic))) { - netif_err(nic, probe, nic->netdev, "Cannot alloc driver memory, aborting\n"); - goto err_out_iounmap; - } - - if ((err = e100_eeprom_load(nic))) - goto err_out_free; - - e100_phy_init(nic); - - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); - memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN); - if (!is_valid_ether_addr(netdev->perm_addr)) { - if (!eeprom_bad_csum_allow) { - netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, aborting\n"); - err = -EAGAIN; - goto err_out_free; - } else { - netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, you MUST configure one.\n"); - } - } - - /* Wol magic packet can be enabled from eeprom */ - if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { - nic->flags |= wol_magic; - device_set_wakeup_enable(&pdev->dev, true); - } - - /* ack any pending wake events, disable PME */ - pci_pme_active(pdev, false); - - strcpy(netdev->name, "eth%d"); - if ((err = register_netdev(netdev))) { - netif_err(nic, probe, nic->netdev, "Cannot register net device, aborting\n"); - goto err_out_free; - } - nic->cbs_pool = pci_pool_create(netdev->name, - nic->pdev, - nic->params.cbs.max * sizeof(struct cb), - sizeof(u32), - 0); - netif_info(nic, probe, nic->netdev, - "addr 0x%llx, irq %d, MAC addr %pM\n", - (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), - pdev->irq, netdev->dev_addr); - - return 0; - -err_out_free: - e100_free(nic); -err_out_iounmap: - pci_iounmap(pdev, nic->csr); -err_out_free_res: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out_free_dev: - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); - return err; -} - -static void __devexit e100_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - - if (netdev) { - struct nic *nic = netdev_priv(netdev); - unregister_netdev(netdev); - e100_free(nic); - pci_iounmap(pdev, nic->csr); - pci_pool_destroy(nic->cbs_pool); - free_netdev(netdev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ -#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ -#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (netif_running(netdev)) - e100_down(nic); - netif_device_detach(netdev); - - pci_save_state(pdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, smartspeed | - E100_82552_REV_ANEG | E100_82552_ANEG_NOW); - } - *enable_wake = true; - } else { - *enable_wake = false; - } - - pci_disable_device(pdev); -} - -static int __e100_power_off(struct pci_dev *pdev, bool wake) -{ - if (wake) - return pci_prepare_to_sleep(pdev); - - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -#ifdef CONFIG_PM -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) -{ - bool wake; - __e100_shutdown(pdev, &wake); - return __e100_power_off(pdev, wake); -} - -static int e100_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { - u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED); - - mdio_write(netdev, nic->mii.phy_id, - E100_82552_SMARTSPEED, - smartspeed & ~(E100_82552_REV_ANEG)); - } - - netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - - return 0; -} -#endif /* CONFIG_PM */ - -static void e100_shutdown(struct pci_dev *pdev) -{ - bool wake; - __e100_shutdown(pdev, &wake); - if (system_state == SYSTEM_POWER_OFF) - __e100_power_off(pdev, wake); -} - -/* ------------------ PCI Error Recovery infrastructure -------------- */ -/** - * e100_io_error_detected - called when PCI error is detected. - * @pdev: Pointer to PCI device - * @state: The current pci connection state - */ -static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e100_down(nic); - pci_disable_device(pdev); - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e100_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch. - */ -static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - pr_err("Cannot re-enable PCI device after reset\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - /* Only one device per card can do a reset */ - if (0 != PCI_FUNC(pdev->devfn)) - return PCI_ERS_RESULT_RECOVERED; - e100_hw_reset(nic); - e100_phy_init(nic); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e100_io_resume - resume normal operations - * @pdev: Pointer to PCI device - * - * Resume normal operations after an error recovery - * sequence has been completed. - */ -static void e100_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - - /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); - - netif_device_attach(netdev); - if (netif_running(netdev)) { - e100_open(netdev); - mod_timer(&nic->watchdog, jiffies); - } -} - -static struct pci_error_handlers e100_err_handler = { - .error_detected = e100_io_error_detected, - .slot_reset = e100_io_slot_reset, - .resume = e100_io_resume, -}; - -static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, - .probe = e100_probe, - .remove = __devexit_p(e100_remove), -#ifdef CONFIG_PM - /* Power Management hooks */ - .suspend = e100_suspend, - .resume = e100_resume, -#endif - .shutdown = e100_shutdown, - .err_handler = &e100_err_handler, -}; - -static int __init e100_init_module(void) -{ - if (((1 << debug) - 1) & NETIF_MSG_DRV) { - pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - pr_info("%s\n", DRV_COPYRIGHT); - } - return pci_register_driver(&e100_driver); -} - -static void __exit e100_cleanup_module(void) -{ - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); diff --git a/devices/r8169-2.6.24-ethercat.c b/devices/r8169-2.6.24-ethercat.c deleted file mode 100644 index 8f71dd26..00000000 --- a/devices/r8169-2.6.24-ethercat.c +++ /dev/null @@ -1,3315 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - * - * vim: noexpandtab - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#ifdef CONFIG_R8169_NAPI -#define NAPI_SUFFIX "-NAPI" -#else -#define NAPI_SUFFIX "" -#endif - -#define RTL8169_VERSION "2.2LK" NAPI_SUFFIX -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -#ifdef CONFIG_R8169_NAPI -#define rtl8169_rx_skb netif_receive_skb -#define rtl8169_rx_hwaccel_skb vlan_hwaccel_receive_skb -#define rtl8169_rx_quota(count, quota) min(count, quota) -#else -#define rtl8169_rx_skb netif_rx -#define rtl8169_rx_hwaccel_skb vlan_hwaccel_rx -#define rtl8169_rx_quota(count, quota) count -#endif - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static const int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14 // 8168C -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - PktCntrDisable = (1 << 7), // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; -#ifdef CONFIG_R8169_NAPI - struct napi_struct napi; -#endif - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - void (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - struct delayed_work task; - unsigned features; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("EtherCAT-capable RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); - -#ifdef CONFIG_R8169_NAPI -static int rtl8169_poll(struct napi_struct *napi, int budget); -#endif - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - } else { - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); - } -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int auto_nego, giga_ctrl; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - if (autoneg == AUTONEG_ENABLE) { - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - if (speed == SPEED_10) - auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL; - else if (speed == SPEED_100) - auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL; - else if (speed == SPEED_1000) - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - - if (duplex == DUPLEX_HALF) - auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL); - - if (duplex == DUPLEX_FULL) - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF); - - /* This tweak comes straight from Realtek's driver. */ - if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && - ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16))) { - auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA; - } - } - - /* The 8100e/8101e do Fast Ethernet only. */ - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && - netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - } - - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version == RTL_GIGA_MAC_VER_17)) { - /* Vendor specific (0x1f) and reserved (0x0e) MII registers. */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - int ret; - - if (tp->vlgrp && (opts2 & RxVlanTag)) { - rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ -} - -static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 status; - - cmd->supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP; - - cmd->autoneg = 1; - cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; - - if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) - cmd->advertising |= ADVERTISED_10baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) - cmd->advertising |= ADVERTISED_10baseT_Full; - if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) - cmd->advertising |= ADVERTISED_100baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) - cmd->advertising |= ADVERTISED_100baseT_Full; - if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) - cmd->advertising |= ADVERTISED_1000baseT_Full; - - status = RTL_R8(PHYstatus); - - if (status & _1000bpsF) - cmd->speed = SPEED_1000; - else if (status & _100bps) - cmd->speed = SPEED_100; - else if (status & _10bps) - cmd->speed = SPEED_10; - - if (status & TxFlowCtrl) - cmd->advertising |= ADVERTISED_Asym_Pause; - if (status & RxFlowCtrl) - cmd->advertising |= ADVERTISED_Pause; - - cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? - DUPLEX_FULL : DUPLEX_HALF; -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return 0; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - - ASSERT_RTNL(); - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_32BIT_MASK; - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (RTL_R32(CounterAddrLow) & CounterDump) { - if (msleep_interruptible(1)) - break; - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underun); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168B family. */ - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */ - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; - - if (p->mask == 0x00000000) { - struct pci_dev *pdev = tp->pci_dev; - - dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg); - } -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cx_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168cx_hw_phy_config(ioaddr); - break; - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - if (!netif_running(dev)) - return -ENODEV; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned msi; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .msi = 0 - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .msi = RTL_FEATURE_MSI - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .msi = RTL_FEATURE_MSI - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->msi) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - pci_set_master(pdev); - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - /* Unneeded ? Don't mess with Mrs. Murphy. */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - rtl8169_print_mac_version(tp); - - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i < 0) { - /* Unknown chip: assume array element #0, original RTL-8169 */ - if (netif_msg_probe(tp)) { - dev_printk(KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming %s\n", - rtl_chip_info[0].name); - } - i++; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - - dev->do_ioctl = rtl8169_ioctl; - } - - /* Get MAC address. FIXME: read EEPROM */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - dev->open = rtl8169_open; - dev->hard_start_xmit = rtl8169_start_xmit; - dev->get_stats = rtl8169_get_stats; - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->stop = rtl8169_close; - dev->tx_timeout = rtl8169_tx_timeout; - dev->set_multicast_list = rtl_set_rx_mode; - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - dev->change_mtu = rtl8169_change_mtu; - dev->set_mac_address = rtl_set_mac_address; - -#ifdef CONFIG_R8169_NAPI - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); -#endif - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = rtl8169_vlan_rx_register; -#endif - -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8169_netpoll; -#endif - - tp->intr_mask = 0xffff; - tp->pci_dev = pdev; - tp->mmio_addr = ioaddr; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - spin_lock_init(&tp->lock); - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - } - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_5; - } - } - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - -#ifdef CONFIG_R8169_NAPI - napi_enable(&tp->napi); -#endif - } - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, 16383); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - u8 ctl; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - /* Tx performance tweak. */ - pci_read_config_byte(pdev, 0x69, &ctl); - ctl = (ctl & ~0x70) | 0x50; - pci_write_config_byte(pdev, 0x69, ctl); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - pci_write_config_word(pdev, 0x68, 0x00); - pci_write_config_word(pdev, 0x69, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - -#ifdef CONFIG_R8169_NAPI - napi_enable(&tp->napi); -#endif - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ -#ifdef CONFIG_R8169_NAPI - napi_disable(&tp->napi); -#endif - - rtl8169_irq_mask_and_ack(ioaddr); - -#ifdef CONFIG_R8169_NAPI - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -#endif -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - - if (unlikely(len < ETH_ZLEN)) { - if (skb_padto(skb, ETH_ZLEN)) - goto err_update_stats; - len = ETH_ZLEN; - } - - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - dev->trans_start = jiffies; - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev) { - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - } - -out: - return ret; - -err_stop: - if (!tp->ecdev) - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; -err_update_stats: - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - if (!tp->ecdev) - dev_kfree_skb_irq(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = rtl8169_rx_quota(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (tp->ecdev) { - pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - - ecdev_receive(tp->ecdev, skb->data, pkt_size); - - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - tp->ec_watchdog_jiffies = jiffies; - } else { - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - rtl8169_rx_skb(skb); - } - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - if (tp->ecdev) { - /* descriptors are cleaned up immediately. */ - tp->dirty_rx = tp->cur_rx; - } else { - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - } - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - int boguscnt = max_interrupt_work; - void __iomem *ioaddr = tp->mmio_addr; - int status; - int handled = 0; - - do { - status = RTL_R16(IntrStatus); - - /* hotplug/major error/no more work/shared irq */ - if ((status == 0xFFFF) || !status) - break; - - handled = 1; - - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - goto out; - } - - status &= tp->intr_mask; - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - - if (!(status & tp->intr_event)) - break; - - /* Work around for rx fifo overflow */ - if (!tp->ecdev && unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(!tp->ecdev && (status & SYSErr))) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - -#ifdef CONFIG_R8169_NAPI - if (tp->ecdev) { - /* Rx interrupt */ - if (status & (RxOK | RxOverflow | RxFIFOOver)) - rtl8169_rx_interrupt(dev, tp, ioaddr, ~(u32)0); - - /* Tx interrupt */ - if (status & (TxOK | TxErr)) - rtl8169_tx_interrupt(dev, tp, ioaddr); - - } else if (status & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(netif_rx_schedule_prep(dev, &tp->napi))) - __netif_rx_schedule(dev, &tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - break; -#else - /* Rx interrupt */ - if (status & (RxOK | RxOverflow | RxFIFOOver)) - rtl8169_rx_interrupt(dev, tp, ioaddr, ~(u32)0); - - /* Tx interrupt */ - if (status & (TxOK | TxErr)) - rtl8169_tx_interrupt(dev, tp, ioaddr); -#endif - - boguscnt--; - } while (boguscnt > 0); - - if (!tp->ecdev) { - if (boguscnt <= 0) { - if (netif_msg_intr(tp) && net_ratelimit() ) { - printk(KERN_WARNING - "%s: Too much work at interrupt!\n", dev->name); - } - /* Clear all interrupt sources. */ - RTL_W16(IntrStatus, 0xffff); - } - } -out: - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_R8169_NAPI -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - netif_rx_complete(dev, napi); - tp->intr_mask = 0xffff; - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} -#endif - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - if (!tp->ecdev) { - netif_stop_queue(dev); - -#ifdef CONFIG_R8169_NAPI - napi_disable(&tp->napi); -#endif - } - -core_down: - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); - - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); - - if (!tp->ecdev) - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16) || - (tp->mac_version == RTL_GIGA_MAC_VER_17)) { - mc_filter[0] = 0xffffffff; - mc_filter[1] = 0xffffffff; - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - if (tp->ecdev) - return -EBUSY; - - if (!netif_running(dev)) - goto out_pci_suspend; - - netif_device_detach(dev); - netif_stop_queue(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); - - spin_unlock_irq(&tp->lock); - -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int rtl8169_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, -#endif -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.24-orig.c b/devices/r8169-2.6.24-orig.c deleted file mode 100644 index 3acfeeab..00000000 --- a/devices/r8169-2.6.24-orig.c +++ /dev/null @@ -1,3209 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifdef CONFIG_R8169_NAPI -#define NAPI_SUFFIX "-NAPI" -#else -#define NAPI_SUFFIX "" -#endif - -#define RTL8169_VERSION "2.2LK" NAPI_SUFFIX -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -#ifdef CONFIG_R8169_NAPI -#define rtl8169_rx_skb netif_receive_skb -#define rtl8169_rx_hwaccel_skb vlan_hwaccel_receive_skb -#define rtl8169_rx_quota(count, quota) min(count, quota) -#else -#define rtl8169_rx_skb netif_rx -#define rtl8169_rx_hwaccel_skb vlan_hwaccel_rx -#define rtl8169_rx_quota(count, quota) count -#endif - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static const int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14 // 8168C -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - PktCntrDisable = (1 << 7), // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; -#ifdef CONFIG_R8169_NAPI - struct napi_struct napi; -#endif - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - void (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - struct delayed_work task; - unsigned features; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); - -#ifdef CONFIG_R8169_NAPI -static int rtl8169_poll(struct napi_struct *napi, int budget); -#endif - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int auto_nego, giga_ctrl; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - if (autoneg == AUTONEG_ENABLE) { - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - if (speed == SPEED_10) - auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL; - else if (speed == SPEED_100) - auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL; - else if (speed == SPEED_1000) - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - - if (duplex == DUPLEX_HALF) - auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL); - - if (duplex == DUPLEX_FULL) - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF); - - /* This tweak comes straight from Realtek's driver. */ - if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && - ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16))) { - auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA; - } - } - - /* The 8100e/8101e do Fast Ethernet only. */ - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && - netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - } - - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version == RTL_GIGA_MAC_VER_17)) { - /* Vendor specific (0x1f) and reserved (0x0e) MII registers. */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - int ret; - - if (tp->vlgrp && (opts2 & RxVlanTag)) { - rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ -} - -static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 status; - - cmd->supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP; - - cmd->autoneg = 1; - cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; - - if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) - cmd->advertising |= ADVERTISED_10baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) - cmd->advertising |= ADVERTISED_10baseT_Full; - if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) - cmd->advertising |= ADVERTISED_100baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) - cmd->advertising |= ADVERTISED_100baseT_Full; - if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) - cmd->advertising |= ADVERTISED_1000baseT_Full; - - status = RTL_R8(PHYstatus); - - if (status & _1000bpsF) - cmd->speed = SPEED_1000; - else if (status & _100bps) - cmd->speed = SPEED_100; - else if (status & _10bps) - cmd->speed = SPEED_10; - - if (status & TxFlowCtrl) - cmd->advertising |= ADVERTISED_Asym_Pause; - if (status & RxFlowCtrl) - cmd->advertising |= ADVERTISED_Pause; - - cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? - DUPLEX_FULL : DUPLEX_HALF; -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return 0; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - - ASSERT_RTNL(); - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_32BIT_MASK; - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (RTL_R32(CounterAddrLow) & CounterDump) { - if (msleep_interruptible(1)) - break; - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underun); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168B family. */ - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */ - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; - - if (p->mask == 0x00000000) { - struct pci_dev *pdev = tp->pci_dev; - - dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg); - } -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cx_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168cx_hw_phy_config(ioaddr); - break; - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - if (!netif_running(dev)) - return -ENODEV; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned msi; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .msi = 0 - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .msi = RTL_FEATURE_MSI - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .msi = RTL_FEATURE_MSI - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->msi) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - pci_set_master(pdev); - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - /* Unneeded ? Don't mess with Mrs. Murphy. */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - rtl8169_print_mac_version(tp); - - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i < 0) { - /* Unknown chip: assume array element #0, original RTL-8169 */ - if (netif_msg_probe(tp)) { - dev_printk(KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming %s\n", - rtl_chip_info[0].name); - } - i++; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - - dev->do_ioctl = rtl8169_ioctl; - } - - /* Get MAC address. FIXME: read EEPROM */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - dev->open = rtl8169_open; - dev->hard_start_xmit = rtl8169_start_xmit; - dev->get_stats = rtl8169_get_stats; - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->stop = rtl8169_close; - dev->tx_timeout = rtl8169_tx_timeout; - dev->set_multicast_list = rtl_set_rx_mode; - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - dev->change_mtu = rtl8169_change_mtu; - dev->set_mac_address = rtl_set_mac_address; - -#ifdef CONFIG_R8169_NAPI - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); -#endif - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = rtl8169_vlan_rx_register; -#endif - -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8169_netpoll; -#endif - - tp->intr_mask = 0xffff; - tp->pci_dev = pdev; - tp->mmio_addr = ioaddr; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - spin_lock_init(&tp->lock); - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - -#ifdef CONFIG_R8169_NAPI - napi_enable(&tp->napi); -#endif - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, 16383); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - u8 ctl; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - /* Tx performance tweak. */ - pci_read_config_byte(pdev, 0x69, &ctl); - ctl = (ctl & ~0x70) | 0x50; - pci_write_config_byte(pdev, 0x69, ctl); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - pci_write_config_word(pdev, 0x68, 0x00); - pci_write_config_word(pdev, 0x69, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - -#ifdef CONFIG_R8169_NAPI - napi_enable(&tp->napi); -#endif - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ -#ifdef CONFIG_R8169_NAPI - napi_disable(&tp->napi); -#endif - - rtl8169_irq_mask_and_ack(ioaddr); - -#ifdef CONFIG_R8169_NAPI - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -#endif -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - - if (unlikely(len < ETH_ZLEN)) { - if (skb_padto(skb, ETH_ZLEN)) - goto err_update_stats; - len = ETH_ZLEN; - } - - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - dev->trans_start = jiffies; - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - -out: - return ret; - -err_stop: - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; -err_update_stats: - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - dev_kfree_skb_irq(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = rtl8169_rx_quota(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - rtl8169_rx_skb(skb); - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - int boguscnt = max_interrupt_work; - void __iomem *ioaddr = tp->mmio_addr; - int status; - int handled = 0; - - do { - status = RTL_R16(IntrStatus); - - /* hotplug/major error/no more work/shared irq */ - if ((status == 0xFFFF) || !status) - break; - - handled = 1; - - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - goto out; - } - - status &= tp->intr_mask; - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - - if (!(status & tp->intr_event)) - break; - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - -#ifdef CONFIG_R8169_NAPI - if (status & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(netif_rx_schedule_prep(dev, &tp->napi))) - __netif_rx_schedule(dev, &tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - break; -#else - /* Rx interrupt */ - if (status & (RxOK | RxOverflow | RxFIFOOver)) - rtl8169_rx_interrupt(dev, tp, ioaddr, ~(u32)0); - - /* Tx interrupt */ - if (status & (TxOK | TxErr)) - rtl8169_tx_interrupt(dev, tp, ioaddr); -#endif - - boguscnt--; - } while (boguscnt > 0); - - if (boguscnt <= 0) { - if (netif_msg_intr(tp) && net_ratelimit() ) { - printk(KERN_WARNING - "%s: Too much work at interrupt!\n", dev->name); - } - /* Clear all interrupt sources. */ - RTL_W16(IntrStatus, 0xffff); - } -out: - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_R8169_NAPI -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - netif_rx_complete(dev, napi); - tp->intr_mask = 0xffff; - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} -#endif - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - -#ifdef CONFIG_R8169_NAPI - napi_disable(&tp->napi); -#endif - -core_down: - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16) || - (tp->mac_version == RTL_GIGA_MAC_VER_17)) { - mc_filter[0] = 0xffffffff; - mc_filter[1] = 0xffffffff; - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - if (!netif_running(dev)) - goto out_pci_suspend; - - netif_device_detach(dev); - netif_stop_queue(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); - - spin_unlock_irq(&tp->lock); - -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int rtl8169_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, -#endif -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.27-ethercat.c b/devices/r8169-2.6.27-ethercat.c deleted file mode 100644 index 922d3928..00000000 --- a/devices/r8169-2.6.27-ethercat.c +++ /dev/null @@ -1,3558 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - * - * vim: noexpandtab - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static const int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14 // 8168C -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("EtherCAT-capable RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - } else { - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); - } -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - tp->phy_auto_nego_reg = auto_nego; - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_32BIT_MASK; - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168B family. */ - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cx_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168cx_hw_phy_config(ioaddr); - break; - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - if (!netif_running(dev)) - return -ENODEV; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - pci_set_master(pdev); - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_5; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - - dev->do_ioctl = rtl8169_ioctl; - } - - /* Get MAC address. FIXME: read EEPROM */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - dev->open = rtl8169_open; - dev->hard_start_xmit = rtl8169_start_xmit; - dev->get_stats = rtl8169_get_stats; - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->stop = rtl8169_close; - dev->tx_timeout = rtl8169_tx_timeout; - dev->set_multicast_list = rtl_set_rx_mode; - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - dev->change_mtu = rtl8169_change_mtu; - dev->set_mac_address = rtl_set_mac_address; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = rtl8169_vlan_rx_register; -#endif - -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8169_netpoll; -#endif - - tp->intr_mask = 0xffff; - tp->mmio_addr = ioaddr; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - spin_lock_init(&tp->lock); - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - } - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_5; - } - } - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - } - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_half_dup | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - dev->trans_start = jiffies; - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev) { - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - } - -out: - return ret; - -err_stop: - if (!tp->ecdev) - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - if (!tp->ecdev) - dev_kfree_skb_irq(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (tp->ecdev) { - pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - - ecdev_receive(tp->ecdev, skb->data, pkt_size); - - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - tp->ec_watchdog_jiffies = jiffies; - } else { - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - } - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - if (tp->ecdev) { - /* descriptors are cleaned up immediately. */ - tp->dirty_rx = tp->cur_rx; - } else { - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - } - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(!tp->ecdev && (status & SYSErr))) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - netif_rx_complete(dev, napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - if (!tp->ecdev) { - netif_stop_queue(dev); - - napi_disable(&tp->napi); - } - -core_down: - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); - - if (!tp->ecdev) - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - if (tp->ecdev) - return -EBUSY; - - if (!netif_running(dev)) - goto out_pci_suspend; - - netif_device_detach(dev); - netif_stop_queue(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int rtl8169_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, -#endif -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.27-orig.c b/devices/r8169-2.6.27-orig.c deleted file mode 100644 index fbc121c0..00000000 --- a/devices/r8169-2.6.27-orig.c +++ /dev/null @@ -1,3463 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static const int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14 // 8168C -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - tp->phy_auto_nego_reg = auto_nego; - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_32BIT_MASK; - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168B family. */ - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cx_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168cx_hw_phy_config(ioaddr); - break; - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - if (!netif_running(dev)) - return -ENODEV; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - pci_set_master(pdev); - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_5; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - - dev->do_ioctl = rtl8169_ioctl; - } - - /* Get MAC address. FIXME: read EEPROM */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - dev->open = rtl8169_open; - dev->hard_start_xmit = rtl8169_start_xmit; - dev->get_stats = rtl8169_get_stats; - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->stop = rtl8169_close; - dev->tx_timeout = rtl8169_tx_timeout; - dev->set_multicast_list = rtl_set_rx_mode; - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - dev->change_mtu = rtl8169_change_mtu; - dev->set_mac_address = rtl_set_mac_address; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = rtl8169_vlan_rx_register; -#endif - -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8169_netpoll; -#endif - - tp->intr_mask = 0xffff; - tp->mmio_addr = ioaddr; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - spin_lock_init(&tp->lock); - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_half_dup | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - dev->trans_start = jiffies; - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - -out: - return ret; - -err_stop: - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - dev_kfree_skb_irq(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - netif_rx_complete(dev, napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - -core_down: - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - if (!netif_running(dev)) - goto out_pci_suspend; - - netif_device_detach(dev); - netif_stop_queue(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int rtl8169_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, -#endif -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.28-ethercat.c b/devices/r8169-2.6.28-ethercat.c deleted file mode 100644 index fd5cb413..00000000 --- a/devices/r8169-2.6.28-ethercat.c +++ /dev/null @@ -1,3941 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - * - * vim: noexpandtab - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static const int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19 // 8168D -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("EtherCAT-capable RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static void ec_poll(struct net_device *dev); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - } else { - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); - } -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int auto_nego, giga_ctrl; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - if (autoneg == AUTONEG_ENABLE) { - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - if (speed == SPEED_10) - auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL; - else if (speed == SPEED_100) - auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL; - else if (speed == SPEED_1000) - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - - if (duplex == DUPLEX_HALF) - auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL); - - if (duplex == DUPLEX_FULL) - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF); - - /* This tweak comes straight from Realtek's driver. */ - if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && - ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16))) { - auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA; - } - } - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || - (tp->mac_version == RTL_GIGA_MAC_VER_08) || - (tp->mac_version == RTL_GIGA_MAC_VER_09) || - (tp->mac_version == RTL_GIGA_MAC_VER_10) || - (tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && - netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - } - - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - - ASSERT_RTNL(); - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_32BIT_MASK; - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (RTL_R32(CounterAddrLow) & CounterDump) { - if (msleep_interruptible(1)) - break; - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underun); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */ - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; - - if (p->mask == 0x00000000) { - struct pci_dev *pdev = tp->pci_dev; - - dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg); - } -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x09, 0x2770 }, - { 0x08, 0x04d0 }, - { 0x0b, 0xad15 }, - { 0x0c, 0x5bf0 }, - { 0x1c, 0xf101 }, - { 0x1f, 0x0003 }, - { 0x14, 0x94d7 }, - { 0x12, 0xf4d6 }, - { 0x09, 0xca0f }, - { 0x1f, 0x0002 }, - { 0x0b, 0x0b10 }, - { 0x0c, 0xd1f7 }, - { 0x1f, 0x0002 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0000 }, - { 0x14, 0x0060 }, - { 0x1f, 0x0000 }, - { 0x0d, 0xf8a0 }, - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (mdio_read(ioaddr, 0x06) == 0xc400) { - struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x01, 0x0300 }, - { 0x1f, 0x0000 }, - { 0x11, 0x401c }, - { 0x16, 0x4100 }, - { 0x1f, 0x0005 }, - { 0x07, 0x0010 }, - { 0x05, 0x83dc }, - { 0x06, 0x087d }, - { 0x05, 0x8300 }, - { 0x06, 0x0101 }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbef }, - { 0x06, 0x79e2 }, - { 0x06, 0x835f }, - { 0x06, 0xe0f8 }, - { 0x06, 0x9ae1 }, - { 0x06, 0xf89b }, - { 0x06, 0xef31 }, - { 0x06, 0x3b65 }, - { 0x06, 0xaa07 }, - { 0x06, 0x81e4 }, - { 0x06, 0xf89a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x9baf }, - { 0x06, 0x06ae }, - { 0x05, 0x83dc }, - { 0x06, 0x8300 }, - }; - - rtl_phy_write(ioaddr, phy_reg_init_1, - ARRAY_SIZE(phy_reg_init_1)); - } - - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - if (!netif_running(dev)) - return -ENODEV; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - pci_set_master(pdev); - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - /* Unknown chip: assume array element #0, original RTL-8169 */ - if (netif_msg_probe(tp)) { - dev_printk(KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming %s\n", - rtl_chip_info[0].name); - } - i = 0; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - - dev->do_ioctl = rtl8169_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - dev->open = rtl8169_open; - dev->hard_start_xmit = rtl8169_start_xmit; - dev->get_stats = rtl8169_get_stats; - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->stop = rtl8169_close; - dev->tx_timeout = rtl8169_tx_timeout; - dev->set_multicast_list = rtl_set_rx_mode; - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - dev->change_mtu = rtl8169_change_mtu; - dev->set_mac_address = rtl_set_mac_address; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = rtl8169_vlan_rx_register; -#endif - -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8169_netpoll; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - } - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_5; - } - } - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - } - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, 16383); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_half_dup | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - - if (unlikely(len < ETH_ZLEN)) { - if (skb_padto(skb, ETH_ZLEN)) - goto err_update_stats; - len = ETH_ZLEN; - } - - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - dev->trans_start = jiffies; - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev) { - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - } - -out: - return ret; - -err_stop: - if (!tp->ecdev) - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; -err_update_stats: - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - if (!tp->ecdev) - dev_kfree_skb_irq(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (tp->ecdev) { - pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - - ecdev_receive(tp->ecdev, skb->data, pkt_size); - - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - tp->ec_watchdog_jiffies = jiffies; - } else { - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - } - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - if (tp->ecdev) { - /* descriptors are cleaned up immediately. */ - tp->dirty_rx = tp->cur_rx; - } else { - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - } - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - status = RTL_R16(IntrStatus); - - /* hotplug/major error/no more work/shared irq */ - if ((status == 0xffff) || !status) - goto out; - - handled = 1; - - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - goto out; - } - - status &= tp->intr_mask; - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - - if (!(status & tp->intr_event)) - goto out; - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - goto out; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - goto out; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - if (status & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(netif_rx_schedule_prep(dev, &tp->napi))) - __netif_rx_schedule(dev, &tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } -out: - return IRQ_RETVAL(handled); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, 100); // FIXME - rtl8169_tx_interrupt(dev, tp, tp->mmio_addr); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - netif_rx_complete(dev, napi); - tp->intr_mask = 0xffff; - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - if (!tp->ecdev) { - netif_stop_queue(dev); - - napi_disable(&tp->napi); - - } -core_down: - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); - - if (!tp->ecdev) - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - if (tp->ecdev) - return -EBUSY; - - if (!netif_running(dev)) - goto out_pci_suspend; - - netif_device_detach(dev); - netif_stop_queue(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int rtl8169_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static void rtl_shutdown(struct pci_dev *pdev) -{ - rtl8169_suspend(pdev, PMSG_SUSPEND); -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .shutdown = rtl_shutdown, -#endif -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.28-orig.c b/devices/r8169-2.6.28-orig.c deleted file mode 100644 index 1aaa9436..00000000 --- a/devices/r8169-2.6.28-orig.c +++ /dev/null @@ -1,3843 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static const int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19 // 8168D -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int auto_nego, giga_ctrl; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - if (autoneg == AUTONEG_ENABLE) { - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - if (speed == SPEED_10) - auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL; - else if (speed == SPEED_100) - auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL; - else if (speed == SPEED_1000) - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - - if (duplex == DUPLEX_HALF) - auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL); - - if (duplex == DUPLEX_FULL) - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF); - - /* This tweak comes straight from Realtek's driver. */ - if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && - ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16))) { - auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA; - } - } - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || - (tp->mac_version == RTL_GIGA_MAC_VER_08) || - (tp->mac_version == RTL_GIGA_MAC_VER_09) || - (tp->mac_version == RTL_GIGA_MAC_VER_10) || - (tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && - netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - } - - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - - ASSERT_RTNL(); - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_32BIT_MASK; - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (RTL_R32(CounterAddrLow) & CounterDump) { - if (msleep_interruptible(1)) - break; - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underun); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */ - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; - - if (p->mask == 0x00000000) { - struct pci_dev *pdev = tp->pci_dev; - - dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg); - } -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x09, 0x2770 }, - { 0x08, 0x04d0 }, - { 0x0b, 0xad15 }, - { 0x0c, 0x5bf0 }, - { 0x1c, 0xf101 }, - { 0x1f, 0x0003 }, - { 0x14, 0x94d7 }, - { 0x12, 0xf4d6 }, - { 0x09, 0xca0f }, - { 0x1f, 0x0002 }, - { 0x0b, 0x0b10 }, - { 0x0c, 0xd1f7 }, - { 0x1f, 0x0002 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0000 }, - { 0x14, 0x0060 }, - { 0x1f, 0x0000 }, - { 0x0d, 0xf8a0 }, - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (mdio_read(ioaddr, 0x06) == 0xc400) { - struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x01, 0x0300 }, - { 0x1f, 0x0000 }, - { 0x11, 0x401c }, - { 0x16, 0x4100 }, - { 0x1f, 0x0005 }, - { 0x07, 0x0010 }, - { 0x05, 0x83dc }, - { 0x06, 0x087d }, - { 0x05, 0x8300 }, - { 0x06, 0x0101 }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbef }, - { 0x06, 0x79e2 }, - { 0x06, 0x835f }, - { 0x06, 0xe0f8 }, - { 0x06, 0x9ae1 }, - { 0x06, 0xf89b }, - { 0x06, 0xef31 }, - { 0x06, 0x3b65 }, - { 0x06, 0xaa07 }, - { 0x06, 0x81e4 }, - { 0x06, 0xf89a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x9baf }, - { 0x06, 0x06ae }, - { 0x05, 0x83dc }, - { 0x06, 0x8300 }, - }; - - rtl_phy_write(ioaddr, phy_reg_init_1, - ARRAY_SIZE(phy_reg_init_1)); - } - - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - if (!netif_running(dev)) - return -ENODEV; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - pci_set_master(pdev); - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - /* Unknown chip: assume array element #0, original RTL-8169 */ - if (netif_msg_probe(tp)) { - dev_printk(KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming %s\n", - rtl_chip_info[0].name); - } - i = 0; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - - dev->do_ioctl = rtl8169_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - dev->open = rtl8169_open; - dev->hard_start_xmit = rtl8169_start_xmit; - dev->get_stats = rtl8169_get_stats; - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->stop = rtl8169_close; - dev->tx_timeout = rtl8169_tx_timeout; - dev->set_multicast_list = rtl_set_rx_mode; - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - dev->change_mtu = rtl8169_change_mtu; - dev->set_mac_address = rtl_set_mac_address; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = rtl8169_vlan_rx_register; -#endif - -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = rtl8169_netpoll; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, 16383); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_half_dup | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - - if (unlikely(len < ETH_ZLEN)) { - if (skb_padto(skb, ETH_ZLEN)) - goto err_update_stats; - len = ETH_ZLEN; - } - - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - dev->trans_start = jiffies; - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - -out: - return ret; - -err_stop: - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; -err_update_stats: - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - dev_kfree_skb_irq(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - - dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - status = RTL_R16(IntrStatus); - - /* hotplug/major error/no more work/shared irq */ - if ((status == 0xffff) || !status) - goto out; - - handled = 1; - - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - goto out; - } - - status &= tp->intr_mask; - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - - if (!(status & tp->intr_event)) - goto out; - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - goto out; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - goto out; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - if (status & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(netif_rx_schedule_prep(dev, &tp->napi))) - __netif_rx_schedule(dev, &tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } -out: - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - netif_rx_complete(dev, napi); - tp->intr_mask = 0xffff; - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - -core_down: - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - if (!netif_running(dev)) - goto out_pci_suspend; - - netif_device_detach(dev); - netif_stop_queue(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int rtl8169_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static void rtl_shutdown(struct pci_dev *pdev) -{ - rtl8169_suspend(pdev, PMSG_SUSPEND); -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .shutdown = rtl_shutdown, -#endif -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.29-ethercat.c b/devices/r8169-2.6.29-ethercat.c deleted file mode 100644 index c38a0ca0..00000000 --- a/devices/r8169-2.6.29-ethercat.c +++ /dev/null @@ -1,3971 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - * - * vim: noexpandtab - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static const int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19 // 8168D -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("EtherCAT-capable RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static void ec_poll(struct net_device *dev); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - } else { - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); - } -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int auto_nego, giga_ctrl; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - if (autoneg == AUTONEG_ENABLE) { - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - if (speed == SPEED_10) - auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL; - else if (speed == SPEED_100) - auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL; - else if (speed == SPEED_1000) - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - - if (duplex == DUPLEX_HALF) - auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL); - - if (duplex == DUPLEX_FULL) - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF); - - /* This tweak comes straight from Realtek's driver. */ - if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && - ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16))) { - auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA; - } - } - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || - (tp->mac_version == RTL_GIGA_MAC_VER_08) || - (tp->mac_version == RTL_GIGA_MAC_VER_09) || - (tp->mac_version == RTL_GIGA_MAC_VER_10) || - (tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && - netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - } - - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_32BIT_MASK; - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */ - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; - - if (p->mask == 0x00000000) { - struct pci_dev *pdev = tp->pci_dev; - - dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg); - } -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x09, 0x2770 }, - { 0x08, 0x04d0 }, - { 0x0b, 0xad15 }, - { 0x0c, 0x5bf0 }, - { 0x1c, 0xf101 }, - { 0x1f, 0x0003 }, - { 0x14, 0x94d7 }, - { 0x12, 0xf4d6 }, - { 0x09, 0xca0f }, - { 0x1f, 0x0002 }, - { 0x0b, 0x0b10 }, - { 0x0c, 0xd1f7 }, - { 0x1f, 0x0002 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0000 }, - { 0x14, 0x0060 }, - { 0x1f, 0x0000 }, - { 0x0d, 0xf8a0 }, - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (mdio_read(ioaddr, 0x06) == 0xc400) { - struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x01, 0x0300 }, - { 0x1f, 0x0000 }, - { 0x11, 0x401c }, - { 0x16, 0x4100 }, - { 0x1f, 0x0005 }, - { 0x07, 0x0010 }, - { 0x05, 0x83dc }, - { 0x06, 0x087d }, - { 0x05, 0x8300 }, - { 0x06, 0x0101 }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbef }, - { 0x06, 0x79e2 }, - { 0x06, 0x835f }, - { 0x06, 0xe0f8 }, - { 0x06, 0x9ae1 }, - { 0x06, 0xf89b }, - { 0x06, 0xef31 }, - { 0x06, 0x3b65 }, - { 0x06, 0xaa07 }, - { 0x06, 0x81e4 }, - { 0x06, 0xf89a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x9baf }, - { 0x06, 0x06ae }, - { 0x05, 0x83dc }, - { 0x06, 0x8300 }, - }; - - rtl_phy_write(ioaddr, phy_reg_init_1, - ARRAY_SIZE(phy_reg_init_1)); - } - - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - pci_set_master(pdev); - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - /* Unknown chip: assume array element #0, original RTL-8169 */ - if (netif_msg_probe(tp)) { - dev_printk(KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming %s\n", - rtl_chip_info[0].name); - } - i = 0; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - } - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_5; - } - } - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - } - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, 16383); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_half_dup | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - dev->trans_start = jiffies; - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev) { - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - } - -out: - return ret; - -err_stop: - if (!tp->ecdev) - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - if (!tp->ecdev) - dev_kfree_skb_irq(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (tp->ecdev) { - pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - - ecdev_receive(tp->ecdev, skb->data, pkt_size); - - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - tp->ec_watchdog_jiffies = jiffies; - } else { - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - } - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - if (tp->ecdev) { - /* descriptors are cleaned up immediately. */ - tp->dirty_rx = tp->cur_rx; - } else { - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - } - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - status = RTL_R16(IntrStatus); - - /* hotplug/major error/no more work/shared irq */ - if ((status == 0xffff) || !status) - goto out; - - handled = 1; - - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - goto out; - } - - status &= tp->intr_mask; - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - - if (!(status & tp->intr_event)) - goto out; - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - goto out; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - goto out; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - if (status & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(netif_rx_schedule_prep(&tp->napi))) - __netif_rx_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } -out: - return IRQ_RETVAL(handled); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, 100); // FIXME - rtl8169_tx_interrupt(dev, tp, tp->mmio_addr); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - netif_rx_complete(napi); - tp->intr_mask = 0xffff; - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - if (!tp->ecdev) { - netif_stop_queue(dev); - - napi_disable(&tp->napi); - - } -core_down: - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); - - if (!tp->ecdev) - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - if (tp->ecdev) - return -EBUSY; - - if (!netif_running(dev)) - goto out_pci_suspend; - - netif_device_detach(dev); - netif_stop_queue(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int rtl8169_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static void rtl_shutdown(struct pci_dev *pdev) -{ - rtl8169_suspend(pdev, PMSG_SUSPEND); -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .shutdown = rtl_shutdown, -#endif -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.29-orig.c b/devices/r8169-2.6.29-orig.c deleted file mode 100644 index 9201e5ae..00000000 --- a/devices/r8169-2.6.29-orig.c +++ /dev/null @@ -1,3873 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static const int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19 // 8168D -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int auto_nego, giga_ctrl; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - if (autoneg == AUTONEG_ENABLE) { - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - if (speed == SPEED_10) - auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL; - else if (speed == SPEED_100) - auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL; - else if (speed == SPEED_1000) - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - - if (duplex == DUPLEX_HALF) - auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL); - - if (duplex == DUPLEX_FULL) - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF); - - /* This tweak comes straight from Realtek's driver. */ - if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && - ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16))) { - auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA; - } - } - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || - (tp->mac_version == RTL_GIGA_MAC_VER_08) || - (tp->mac_version == RTL_GIGA_MAC_VER_09) || - (tp->mac_version == RTL_GIGA_MAC_VER_10) || - (tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && - netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - } - - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_32BIT_MASK; - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */ - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; - - if (p->mask == 0x00000000) { - struct pci_dev *pdev = tp->pci_dev; - - dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg); - } -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x09, 0x2770 }, - { 0x08, 0x04d0 }, - { 0x0b, 0xad15 }, - { 0x0c, 0x5bf0 }, - { 0x1c, 0xf101 }, - { 0x1f, 0x0003 }, - { 0x14, 0x94d7 }, - { 0x12, 0xf4d6 }, - { 0x09, 0xca0f }, - { 0x1f, 0x0002 }, - { 0x0b, 0x0b10 }, - { 0x0c, 0xd1f7 }, - { 0x1f, 0x0002 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0000 }, - { 0x14, 0x0060 }, - { 0x1f, 0x0000 }, - { 0x0d, 0xf8a0 }, - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (mdio_read(ioaddr, 0x06) == 0xc400) { - struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x01, 0x0300 }, - { 0x1f, 0x0000 }, - { 0x11, 0x401c }, - { 0x16, 0x4100 }, - { 0x1f, 0x0005 }, - { 0x07, 0x0010 }, - { 0x05, 0x83dc }, - { 0x06, 0x087d }, - { 0x05, 0x8300 }, - { 0x06, 0x0101 }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbef }, - { 0x06, 0x79e2 }, - { 0x06, 0x835f }, - { 0x06, 0xe0f8 }, - { 0x06, 0x9ae1 }, - { 0x06, 0xf89b }, - { 0x06, 0xef31 }, - { 0x06, 0x3b65 }, - { 0x06, 0xaa07 }, - { 0x06, 0x81e4 }, - { 0x06, 0xf89a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x9baf }, - { 0x06, 0x06ae }, - { 0x05, 0x83dc }, - { 0x06, 0x8300 }, - }; - - rtl_phy_write(ioaddr, phy_reg_init_1, - ARRAY_SIZE(phy_reg_init_1)); - } - - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - pci_set_master(pdev); - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - /* Unknown chip: assume array element #0, original RTL-8169 */ - if (netif_msg_probe(tp)) { - dev_printk(KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming %s\n", - rtl_chip_info[0].name); - } - i = 0; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, 16383); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_half_dup | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - dev->trans_start = jiffies; - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - -out: - return ret; - -err_stop: - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - dev_kfree_skb_irq(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - status = RTL_R16(IntrStatus); - - /* hotplug/major error/no more work/shared irq */ - if ((status == 0xffff) || !status) - goto out; - - handled = 1; - - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - goto out; - } - - status &= tp->intr_mask; - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - - if (!(status & tp->intr_event)) - goto out; - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - goto out; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - goto out; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - if (status & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(netif_rx_schedule_prep(&tp->napi))) - __netif_rx_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } -out: - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - netif_rx_complete(napi); - tp->intr_mask = 0xffff; - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - -core_down: - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - if (!netif_running(dev)) - goto out_pci_suspend; - - netif_device_detach(dev); - netif_stop_queue(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int rtl8169_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static void rtl_shutdown(struct pci_dev *pdev) -{ - rtl8169_suspend(pdev, PMSG_SUSPEND); -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .shutdown = rtl_shutdown, -#endif -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.31-ethercat.c b/devices/r8169-2.6.31-ethercat.c deleted file mode 100644 index 8c7e66a7..00000000 --- a/devices/r8169-2.6.31-ethercat.c +++ /dev/null @@ -1,4010 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - * - * vim: noexpandtab - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../globals.h" -#include "ecdev.h" - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19 // 8168D -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("EtherCAT-capable RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static void ec_poll(struct net_device *dev); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - } else { - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); - } -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x09, 0x2770 }, - { 0x08, 0x04d0 }, - { 0x0b, 0xad15 }, - { 0x0c, 0x5bf0 }, - { 0x1c, 0xf101 }, - { 0x1f, 0x0003 }, - { 0x14, 0x94d7 }, - { 0x12, 0xf4d6 }, - { 0x09, 0xca0f }, - { 0x1f, 0x0002 }, - { 0x0b, 0x0b10 }, - { 0x0c, 0xd1f7 }, - { 0x1f, 0x0002 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0000 }, - { 0x14, 0x0060 }, - { 0x1f, 0x0000 }, - { 0x0d, 0xf8a0 }, - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (mdio_read(ioaddr, 0x06) == 0xc400) { - struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x01, 0x0300 }, - { 0x1f, 0x0000 }, - { 0x11, 0x401c }, - { 0x16, 0x4100 }, - { 0x1f, 0x0005 }, - { 0x07, 0x0010 }, - { 0x05, 0x83dc }, - { 0x06, 0x087d }, - { 0x05, 0x8300 }, - { 0x06, 0x0101 }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbef }, - { 0x06, 0x79e2 }, - { 0x06, 0x835f }, - { 0x06, 0xe0f8 }, - { 0x06, 0x9ae1 }, - { 0x06, 0xf89b }, - { 0x06, 0xef31 }, - { 0x06, 0x3b65 }, - { 0x06, 0xaa07 }, - { 0x06, 0x81e4 }, - { 0x06, 0xf89a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x9baf }, - { 0x06, 0x06ae }, - { 0x05, 0x83dc }, - { 0x06, 0x8300 }, - }; - - rtl_phy_write(ioaddr, phy_reg_init_1, - ARRAY_SIZE(phy_reg_init_1)); - } - - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_5; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - } - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_5; - } - } - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - } - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_half_dup | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev) { - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - } - -out: - return ret; - -err_stop: - if (!tp->ecdev) - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - if (!tp->ecdev) - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (tp->ecdev) { - pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - - ecdev_receive(tp->ecdev, skb->data, pkt_size); - - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - tp->ec_watchdog_jiffies = jiffies; - } else { - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - } - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - if (tp->ecdev) { - /* descriptors are cleaned up immediately. */ - tp->dirty_rx = tp->cur_rx; - } else { - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - } - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, 100); // FIXME - rtl8169_tx_interrupt(dev, tp, tp->mmio_addr); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - if (!tp->ecdev) { - netif_stop_queue(dev); - - napi_disable(&tp->napi); - - } -core_down: - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); - - if (!tp->ecdev) - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.31-orig.c b/devices/r8169-2.6.31-orig.c deleted file mode 100644 index b82780d8..00000000 --- a/devices/r8169-2.6.31-orig.c +++ /dev/null @@ -1,3911 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19 // 8168D -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x09, 0x2770 }, - { 0x08, 0x04d0 }, - { 0x0b, 0xad15 }, - { 0x0c, 0x5bf0 }, - { 0x1c, 0xf101 }, - { 0x1f, 0x0003 }, - { 0x14, 0x94d7 }, - { 0x12, 0xf4d6 }, - { 0x09, 0xca0f }, - { 0x1f, 0x0002 }, - { 0x0b, 0x0b10 }, - { 0x0c, 0xd1f7 }, - { 0x1f, 0x0002 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0000 }, - { 0x14, 0x0060 }, - { 0x1f, 0x0000 }, - { 0x0d, 0xf8a0 }, - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (mdio_read(ioaddr, 0x06) == 0xc400) { - struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x01, 0x0300 }, - { 0x1f, 0x0000 }, - { 0x11, 0x401c }, - { 0x16, 0x4100 }, - { 0x1f, 0x0005 }, - { 0x07, 0x0010 }, - { 0x05, 0x83dc }, - { 0x06, 0x087d }, - { 0x05, 0x8300 }, - { 0x06, 0x0101 }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbef }, - { 0x06, 0x79e2 }, - { 0x06, 0x835f }, - { 0x06, 0xe0f8 }, - { 0x06, 0x9ae1 }, - { 0x06, 0xf89b }, - { 0x06, 0xef31 }, - { 0x06, 0x3b65 }, - { 0x06, 0xaa07 }, - { 0x06, 0x81e4 }, - { 0x06, 0xf89a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x9baf }, - { 0x06, 0x06ae }, - { 0x05, 0x83dc }, - { 0x06, 0x8300 }, - }; - - rtl_phy_write(ioaddr, phy_reg_init_1, - ARRAY_SIZE(phy_reg_init_1)); - } - - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_5; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_half_dup | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int ret = NETDEV_TX_OK; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - -out: - return ret; - -err_stop: - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - dev->stats.tx_dropped++; - goto out; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - -core_down: - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.32-ethercat.c b/devices/r8169-2.6.32-ethercat.c deleted file mode 100644 index ee83fe06..00000000 --- a/devices/r8169-2.6.32-ethercat.c +++ /dev/null @@ -1,5027 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "../globals.h" -#include "ecdev.h" - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("EtherCAT-capable RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static void ec_poll(struct net_device *dev); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - } else { - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); - } -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_5; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - } - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x9cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_5; - } - } - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int max_frame = dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - - tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - } - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev) { - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - } - - return NETDEV_TX_OK; - -err_stop: - if (!tp->ecdev) - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - if (!tp->ecdev) - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (tp->ecdev) { - pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - - ecdev_receive(tp->ecdev, skb->data, pkt_size); - - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - tp->ec_watchdog_jiffies = jiffies; - } else { - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - } - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - if (tp->ecdev) { - /* descriptors are cleaned up immediately. */ - tp->dirty_rx = tp->cur_rx; - } else { - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - } - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, 100); // FIXME - rtl8169_tx_interrupt(dev, tp, tp->mmio_addr); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - if (!tp->ecdev) { - netif_stop_queue(dev); - - napi_disable(&tp->napi); - } - -core_down: - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); - - if (!tp->ecdev) - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.32-orig.c b/devices/r8169-2.6.32-orig.c deleted file mode 100644 index 0fe2fc90..00000000 --- a/devices/r8169-2.6.32-orig.c +++ /dev/null @@ -1,4932 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_copybreak = 200; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_5; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x9cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) -{ - unsigned int max_frame = dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - - tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - rtl8169_set_rxbufsize(tp, dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - - return NETDEV_TX_OK; - -err_stop: - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_reserve(skb, NET_IP_ALIGN); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - -core_down: - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.33-ethercat.c b/devices/r8169-2.6.33-ethercat.c deleted file mode 100644 index 09c18c45..00000000 --- a/devices/r8169-2.6.33-ethercat.c +++ /dev/null @@ -1,5045 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "../globals.h" -#include "ecdev.h" - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -/* - * we set our copybreak very high so that we don't have - * to allocate 16k frames all the time (see note in - * rtl8169_open() - */ -static int rx_copybreak = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("EtherCAT-capable RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static void ec_poll(struct net_device *dev); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - } else { - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); - } -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_5; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - } - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x9cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_5; - } - } - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - unsigned int mtu) -{ - unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - - if (max_frame != 16383) - printk(KERN_WARNING "WARNING! Changing of MTU on this NIC" - "May lead to frame reception errors!\n"); - - tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - /* - * Note that we use a magic value here, its wierd I know - * its done because, some subset of rtl8169 hardware suffers from - * a problem in which frames received that are longer than - * the size set in RxMaxSize register return garbage sizes - * when received. To avoid this we need to turn off filtering, - * which is done by setting a value of 16383 in the RxMaxSize register - * and allocating 16k frames to handle the largest possible rx value - * thats what the magic math below does. - */ - rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - } - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev->mtu); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev) { - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - } - - return NETDEV_TX_OK; - -err_stop: - if (!tp->ecdev) - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - if (!tp->ecdev) - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (tp->ecdev) { - pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - - ecdev_receive(tp->ecdev, skb->data, pkt_size); - - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - tp->ec_watchdog_jiffies = jiffies; - } else { - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - } - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - if (tp->ecdev) { - /* descriptors are cleaned up immediately. */ - tp->dirty_rx = tp->cur_rx; - } else { - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - } - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, 100); // FIXME - rtl8169_tx_interrupt(dev, tp, tp->mmio_addr); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - if (!tp->ecdev) { - netif_stop_queue(dev); - - napi_disable(&tp->napi); - } - -core_down: - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); - - if (!tp->ecdev) - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.33-orig.c b/devices/r8169-2.6.33-orig.c deleted file mode 100644 index 67d414b0..00000000 --- a/devices/r8169-2.6.33-orig.c +++ /dev/null @@ -1,4950 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -/* - * we set our copybreak very high so that we don't have - * to allocate 16k frames all the time (see note in - * rtl8169_open() - */ -static int rx_copybreak = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - - wol->wolopts = 0; - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - wol->supported = WAKE_ANY; - - spin_lock_irq(&tp->lock); - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(Config3); - if (options & LinkUp) - wol->wolopts |= WAKE_PHY; - if (options & MagicPacket) - wol->wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wol->wolopts |= WAKE_UCAST; - if (options & BWF) - wol->wolopts |= WAKE_BCAST; - if (options & MWF) - wol->wolopts |= WAKE_MCAST; - -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wol->wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC0, low); - RTL_W32(MAC4, high); - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable_2; - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } - rc = -ENODEV; - goto err_out_mwi_3; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi_3; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } - goto err_out_free_res_4; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_4; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_5; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_5; - - pci_set_drvdata(pdev, dev); - - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x9cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); - } - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - -out: - return rc; - -err_out_msi_5: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_4: - pci_release_regions(pdev); -err_out_mwi_3: - pci_clear_mwi(pdev); -err_out_disable_2: - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - unsigned int mtu) -{ - unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - - if (max_frame != 16383) - printk(KERN_WARNING "WARNING! Changing of MTU on this NIC" - "May lead to frame reception errors!\n"); - - tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - - /* - * Note that we use a magic value here, its wierd I know - * its done because, some subset of rtl8169 hardware suffers from - * a problem in which frames received that are longer than - * the size set in RxMaxSize register return garbage sizes - * when received. To avoid this we need to turn off filtering, - * which is done by setting a value of 16383 in the RxMaxSize register - * and allocating 16k frames to handle the largest possible rx value - * thats what the magic math below does. - */ - rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto out; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev->mtu); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - smp_wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - - return NETDEV_TX_OK; - -err_stop: - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - smp_wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - -core_down: - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - - rtl8169_schedule_work(dev, rtl8169_reset_task); -out: - return 0; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.35-ethercat.c b/devices/r8169-2.6.35-ethercat.c deleted file mode 100644 index 26295a1b..00000000 --- a/devices/r8169-2.6.35-ethercat.c +++ /dev/null @@ -1,5121 +0,0 @@ -/* -* r8169.c: RealTek 8169/8168/8101 ethernet driver. -* -* Copyright (c) 2002 ShuChen -* Copyright (c) 2003 - 2007 Francois Romieu -* Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "../globals.h" -#include "ecdev.h" - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -/* - * we set our copybreak very high so that we don't have - * to allocate 16k frames all the time (see note in - * rtl8169_open() - */ -static int rx_copybreak = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - u32 saved_wolopts; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver (EtherCAT)"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static void ec_poll(struct net_device *dev); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after write - * complete indication, but before sending next command. - */ - udelay(20); -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after read - * complete indication, but before sending next command. - */ - udelay(20); - - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - return; - } - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - /* This is to cancel a scheduled suspend if there's one. */ - pm_request_resume(&tp->pci_dev->dev); - netif_carrier_on(dev); - netif_info(tp, ifup, dev, "link up\n"); - } else { - netif_carrier_off(dev); - netif_info(tp, ifdown, dev, "link down\n"); - pm_schedule_suspend(&tp->pci_dev->dev, 100); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - u32 wolopts = 0; - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - return 0; - - options = RTL_R8(Config3); - if (options & LinkUp) - wolopts |= WAKE_PHY; - if (options & MagicPacket) - wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wolopts |= WAKE_UCAST; - if (options & BWF) - wolopts |= WAKE_BCAST; - if (options & MWF) - wolopts |= WAKE_MCAST; - - return wolopts; -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - wol->supported = WAKE_ANY; - wol->wolopts = __rtl8169_get_wol(tp); - - spin_unlock_irq(&tp->lock); -} - -static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - __rtl8169_set_wol(tp, wol->wolopts); - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - netif_warn(tp, link, dev, - "incorrect speed setting refused in TBI mode\n"); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - netif_info(tp, link, dev, - "PHY does not support 1000Mbps\n"); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - netif_warn(tp, link, dev, "PHY reset until link up\n"); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - netif_err(tp, link, dev, "PHY reset failed\n"); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if (RTL_R8(PHYstatus) & TBI_Enable) - netif_info(tp, link, dev, "TBI auto-negotiating\n"); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W32(MAC4, high); - RTL_R32(MAC4); - - RTL_W32(MAC0, low); - RTL_R32(MAC0); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - netif_err(tp, probe, dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - if (pci_set_mwi(pdev) < 0) - netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n"); - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - netif_err(tp, probe, dev, - "region #%d not an MMIO resource, aborting\n", - region); - rc = -ENODEV; - goto err_out_mwi_2; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - netif_err(tp, probe, dev, - "Invalid PCI region size(s), aborting\n"); - rc = -ENODEV; - goto err_out_mwi_2; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - netif_err(tp, probe, dev, "could not request regions\n"); - goto err_out_mwi_2; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - netif_err(tp, probe, dev, "DMA configuration failed\n"); - goto err_out_free_res_3; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_3; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap) - netif_info(tp, probe, dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - netif_notice(tp, probe, dev, - "unknown MAC, using family default\n"); - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_4; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - tp->ec_watchdog_jiffies = jiffies; - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_4; - } - - pci_set_drvdata(pdev, dev); - - netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", - rtl_chip_info[tp->chipset].name, - dev->base_addr, dev->dev_addr, - (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (pci_dev_run_wake(pdev)) { - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); - } - pm_runtime_idle(&pdev->dev); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_4; - } - } - -out: - return rc; - -err_out_msi_4: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_3: - pci_release_regions(pdev); -err_out_mwi_2: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - pm_runtime_get_sync(&pdev->dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - - if (pci_dev_run_wake(pdev)) { - pm_runtime_disable(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); - } - pm_runtime_put_noidle(&pdev->dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - unsigned int mtu) -{ - unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - - if (max_frame != 16383) - printk(KERN_WARNING PFX "WARNING! Changing of MTU on this " - "NIC may lead to frame reception errors!\n"); - - tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - pm_runtime_get_sync(&pdev->dev); - - /* - * Note that we use a magic value here, its wierd I know - * its done because, some subset of rtl8169 hardware suffers from - * a problem in which frames received that are longer than - * the size set in RxMaxSize register return garbage sizes - * when received. To avoid this we need to turn off filtering, - * which is done by setting a value of 16383 in the RxMaxSize register - * and allocating 16k frames to handle the largest possible rx value - * thats what the magic math below does. - */ - rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto err_pm_runtime_put; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - } - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - tp->saved_wolopts = 0; - pm_runtime_put_noidle(&pdev->dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; -err_pm_runtime_put: - pm_runtime_put_noidle(&pdev->dev); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev->mtu); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align, gfp_t gfp) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end, gfp_t gfp) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align, gfp); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit()) - netif_err(tp, drv, dev, - "reinit failure (status = %d). Rescheduling\n", - ret); - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit()) - netif_emerg(tp, intr, dev, "Rx buffers shortage\n"); - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev && TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - - return NETDEV_TX_OK; - -err_stop: - if (!tp->ecdev) - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", - pci_cmd, pci_status); - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - netif_info(tp, intr, dev, "disabling PCI DAC\n"); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - if (!tp->ecdev) - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -/* - * Warning : rtl8169_rx_interrupt() might be called : - * 1) from NAPI (softirq) context - * (polling = 1 : we should call netif_receive_skb()) - * 2) from process context (rtl8169_reset_task()) - * (polling = 0 : we must call netif_rx() instead) - */ -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - int polling = (budget != ~(u32)0) ? 1 : 0; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", - status); - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (tp->ecdev) { - /* reusing parts of rtl8169_try_rx_copy() */ - pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - - ecdev_receive(tp->ecdev, skb->data, pkt_size); - - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - tp->ec_watchdog_jiffies = jiffies; - } else { - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { - if (likely(polling)) - netif_receive_skb(skb); - else - netif_rx(skb); - } - } - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC); - if (!delta && count) - netif_info(tp, intr, dev, "no Rx buffer allocated\n"); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) - netif_emerg(tp, intr, dev, "Rx buffers exhausted\n"); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(!tp->ecdev && (status & RxFIFOOver)) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else - netif_info(tp, intr, dev, - "interrupt %04x in poll\n", status); - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, 100); // FIXME - rtl8169_tx_interrupt(dev, tp, tp->mmio_addr); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - if (!tp->ecdev) { - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - } - -core_down: - if (!tp->ecdev) { - spin_lock_irq(&tp->lock); - } - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - if (!tp->ecdev) { - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - } - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - pm_runtime_get_sync(&pdev->dev); - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 4, mc_filter[1]); - RTL_W32(MAR0 + 0, mc_filter[0]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - rtl8169_net_suspend(dev); - - return 0; -} - -static void __rtl8169_resume(struct net_device *dev) -{ - netif_device_attach(dev); - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - if (netif_running(dev)) - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - tp->saved_wolopts = __rtl8169_get_wol(tp); - __rtl8169_set_wol(tp, WAKE_ANY); - spin_unlock_irq(&tp->lock); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_runtime_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - __rtl8169_set_wol(tp, tp->saved_wolopts); - tp->saved_wolopts = 0; - spin_unlock_irq(&tp->lock); - - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_idle(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - return -EBUSY; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, - .runtime_suspend = rtl8169_runtime_suspend, - .runtime_resume = rtl8169_runtime_resume, - .runtime_idle = rtl8169_runtime_idle, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.35-orig.c b/devices/r8169-2.6.35-orig.c deleted file mode 100644 index ad9833b2..00000000 --- a/devices/r8169-2.6.35-orig.c +++ /dev/null @@ -1,5028 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -/* - * we set our copybreak very high so that we don't have - * to allocate 16k frames all the time (see note in - * rtl8169_open() - */ -static int rx_copybreak = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - u32 saved_wolopts; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after write - * complete indication, but before sending next command. - */ - udelay(20); -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after read - * complete indication, but before sending next command. - */ - udelay(20); - - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - /* This is to cancel a scheduled suspend if there's one. */ - pm_request_resume(&tp->pci_dev->dev); - netif_carrier_on(dev); - netif_info(tp, ifup, dev, "link up\n"); - } else { - netif_carrier_off(dev); - netif_info(tp, ifdown, dev, "link down\n"); - pm_schedule_suspend(&tp->pci_dev->dev, 100); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - u32 wolopts = 0; - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - return 0; - - options = RTL_R8(Config3); - if (options & LinkUp) - wolopts |= WAKE_PHY; - if (options & MagicPacket) - wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wolopts |= WAKE_UCAST; - if (options & BWF) - wolopts |= WAKE_BCAST; - if (options & MWF) - wolopts |= WAKE_MCAST; - - return wolopts; -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - wol->supported = WAKE_ANY; - wol->wolopts = __rtl8169_get_wol(tp); - - spin_unlock_irq(&tp->lock); -} - -static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - __rtl8169_set_wol(tp, wol->wolopts); - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - netif_warn(tp, link, dev, - "incorrect speed setting refused in TBI mode\n"); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - netif_info(tp, link, dev, - "PHY does not support 1000Mbps\n"); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - netif_warn(tp, link, dev, "PHY reset until link up\n"); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - netif_err(tp, link, dev, "PHY reset failed\n"); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if (RTL_R8(PHYstatus) & TBI_Enable) - netif_info(tp, link, dev, "TBI auto-negotiating\n"); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W32(MAC4, high); - RTL_R32(MAC4); - - RTL_W32(MAC0, low); - RTL_R32(MAC0); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - netif_err(tp, probe, dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - if (pci_set_mwi(pdev) < 0) - netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n"); - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - netif_err(tp, probe, dev, - "region #%d not an MMIO resource, aborting\n", - region); - rc = -ENODEV; - goto err_out_mwi_2; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - netif_err(tp, probe, dev, - "Invalid PCI region size(s), aborting\n"); - rc = -ENODEV; - goto err_out_mwi_2; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - netif_err(tp, probe, dev, "could not request regions\n"); - goto err_out_mwi_2; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - netif_err(tp, probe, dev, "DMA configuration failed\n"); - goto err_out_free_res_3; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_3; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap) - netif_info(tp, probe, dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - netif_notice(tp, probe, dev, - "unknown MAC, using family default\n"); - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_4; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_4; - - pci_set_drvdata(pdev, dev); - - netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", - rtl_chip_info[tp->chipset].name, - dev->base_addr, dev->dev_addr, - (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (pci_dev_run_wake(pdev)) { - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); - } - pm_runtime_idle(&pdev->dev); - -out: - return rc; - -err_out_msi_4: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_3: - pci_release_regions(pdev); -err_out_mwi_2: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - pm_runtime_get_sync(&pdev->dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - - if (pci_dev_run_wake(pdev)) { - pm_runtime_disable(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); - } - pm_runtime_put_noidle(&pdev->dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - unsigned int mtu) -{ - unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - - if (max_frame != 16383) - printk(KERN_WARNING PFX "WARNING! Changing of MTU on this " - "NIC may lead to frame reception errors!\n"); - - tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - pm_runtime_get_sync(&pdev->dev); - - /* - * Note that we use a magic value here, its wierd I know - * its done because, some subset of rtl8169 hardware suffers from - * a problem in which frames received that are longer than - * the size set in RxMaxSize register return garbage sizes - * when received. To avoid this we need to turn off filtering, - * which is done by setting a value of 16383 in the RxMaxSize register - * and allocating 16k frames to handle the largest possible rx value - * thats what the magic math below does. - */ - rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto err_pm_runtime_put; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - tp->saved_wolopts = 0; - pm_runtime_put_noidle(&pdev->dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; -err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; -err_pm_runtime_put: - pm_runtime_put_noidle(&pdev->dev); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev->mtu); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align, gfp_t gfp) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end, gfp_t gfp) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align, gfp); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit()) - netif_err(tp, drv, dev, - "reinit failure (status = %d). Rescheduling\n", - ret); - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit()) - netif_emerg(tp, intr, dev, "Rx buffers shortage\n"); - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - - return NETDEV_TX_OK; - -err_stop: - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", - pci_cmd, pci_status); - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - netif_info(tp, intr, dev, "disabling PCI DAC\n"); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (!skb) - goto out; - - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -/* - * Warning : rtl8169_rx_interrupt() might be called : - * 1) from NAPI (softirq) context - * (polling = 1 : we should call netif_receive_skb()) - * 2) from process context (rtl8169_reset_task()) - * (polling = 0 : we must call netif_rx() instead) - */ -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - int polling = (budget != ~(u32)0) ? 1 : 0; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", - status); - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { - if (likely(polling)) - netif_receive_skb(skb); - else - netif_rx(skb); - } - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC); - if (!delta && count) - netif_info(tp, intr, dev, "no Rx buffer allocated\n"); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) - netif_emerg(tp, intr, dev, "Rx buffers exhausted\n"); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else - netif_info(tp, intr, dev, - "interrupt %04x in poll\n", status); - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - -core_down: - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - pm_runtime_get_sync(&pdev->dev); - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 4, mc_filter[1]); - RTL_W32(MAR0 + 0, mc_filter[0]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - rtl8169_net_suspend(dev); - - return 0; -} - -static void __rtl8169_resume(struct net_device *dev) -{ - netif_device_attach(dev); - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - if (netif_running(dev)) - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - tp->saved_wolopts = __rtl8169_get_wol(tp); - __rtl8169_set_wol(tp, WAKE_ANY); - spin_unlock_irq(&tp->lock); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_runtime_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - __rtl8169_set_wol(tp, tp->saved_wolopts); - tp->saved_wolopts = 0; - spin_unlock_irq(&tp->lock); - - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_idle(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - return -EBUSY; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, - .runtime_suspend = rtl8169_runtime_suspend, - .runtime_resume = rtl8169_runtime_resume, - .runtime_idle = rtl8169_runtime_idle, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.36-ethercat.c b/devices/r8169-2.6.36-ethercat.c deleted file mode 100644 index 6cf80677..00000000 --- a/devices/r8169-2.6.36-ethercat.c +++ /dev/null @@ -1,5127 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "../globals.h" -#include "ecdev.h" - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) readl (ioaddr + (reg)) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -/* - * we set our copybreak very high so that we don't have - * to allocate 16k frames all the time (see note in - * rtl8169_open() - */ -static int rx_copybreak = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - u32 saved_wolopts; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Florian Pose "); -MODULE_DESCRIPTION("EtherCAT-capable RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static void ec_poll(struct net_device *dev); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after write - * complete indication, but before sending next command. - */ - udelay(20); -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after read - * complete indication, but before sending next command. - */ - udelay(20); - - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - } else { - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - /* This is to cancel a scheduled suspend if there's one. */ - pm_request_resume(&tp->pci_dev->dev); - netif_carrier_on(dev); - netif_info(tp, ifup, dev, "link up\n"); - } else { - netif_carrier_off(dev); - netif_info(tp, ifdown, dev, "link down\n"); - pm_schedule_suspend(&tp->pci_dev->dev, 100); - } - spin_unlock_irqrestore(&tp->lock, flags); - } -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - u32 wolopts = 0; - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - return 0; - - options = RTL_R8(Config3); - if (options & LinkUp) - wolopts |= WAKE_PHY; - if (options & MagicPacket) - wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wolopts |= WAKE_UCAST; - if (options & BWF) - wolopts |= WAKE_BCAST; - if (options & MWF) - wolopts |= WAKE_MCAST; - - return wolopts; -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - wol->supported = WAKE_ANY; - wol->wolopts = __rtl8169_get_wol(tp); - - spin_unlock_irq(&tp->lock); -} - -static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - __rtl8169_set_wol(tp, wol->wolopts); - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - netif_warn(tp, link, dev, - "incorrect speed setting refused in TBI mode\n"); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - netif_info(tp, link, dev, - "PHY does not support 1000Mbps\n"); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = dma_alloc_coherent(&tp->pci_dev->dev, sizeof(*counters), - &paddr, GFP_KERNEL); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - dma_free_coherent(&tp->pci_dev->dev, sizeof(*counters), counters, - paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - netif_warn(tp, link, dev, "PHY reset until link up\n"); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - netif_err(tp, link, dev, "PHY reset failed\n"); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if (RTL_R8(PHYstatus) & TBI_Enable) - netif_info(tp, link, dev, "TBI auto-negotiating\n"); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W32(MAC4, high); - RTL_R32(MAC4); - - RTL_W32(MAC0, low); - RTL_R32(MAC0); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | RxFIFOOver | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - netif_err(tp, probe, dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - if (pci_set_mwi(pdev) < 0) - netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n"); - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - netif_err(tp, probe, dev, - "region #%d not an MMIO resource, aborting\n", - region); - rc = -ENODEV; - goto err_out_mwi_2; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - netif_err(tp, probe, dev, - "Invalid PCI region size(s), aborting\n"); - rc = -ENODEV; - goto err_out_mwi_2; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - netif_err(tp, probe, dev, "could not request regions\n"); - goto err_out_mwi_2; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - netif_err(tp, probe, dev, "DMA configuration failed\n"); - goto err_out_free_res_3; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_3; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap) - netif_info(tp, probe, dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - netif_notice(tp, probe, dev, - "unknown MAC, using family default\n"); - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_4; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_4; - } - - pci_set_drvdata(pdev, dev); - - netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", - rtl_chip_info[tp->chipset].name, - dev->base_addr, dev->dev_addr, - (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (pci_dev_run_wake(pdev)) - pm_runtime_put_noidle(&pdev->dev); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_4; - } - } - -out: - return rc; - -err_out_msi_4: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_3: - pci_release_regions(pdev); -err_out_mwi_2: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - - if(!tp->ecdev) { - if (pci_dev_run_wake(pdev)) - pm_runtime_get_noresume(&pdev->dev); - } - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - unsigned int mtu) -{ - unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - - if (max_frame != 16383) - printk(KERN_WARNING PFX "WARNING! Changing of MTU on this " - "NIC may lead to frame reception errors!\n"); - - tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - if(!tp->ecdev) - pm_runtime_get_sync(&pdev->dev); - - /* - * Note that we use a magic value here, its wierd I know - * its done because, some subset of rtl8169 hardware suffers from - * a problem in which frames received that are longer than - * the size set in RxMaxSize register return garbage sizes - * when received. To avoid this we need to turn off filtering, - * which is done by setting a value of 16383 in the RxMaxSize register - * and allocating 16k frames to handle the largest possible rx value - * thats what the magic math below does. - */ - rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * dma_alloc_coherent provides more. - */ - tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr, GFP_KERNEL); - if (!tp->TxDescArray) - goto err_pm_runtime_put; - - tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr, GFP_KERNEL); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - } - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - tp->saved_wolopts = 0; - if(!tp->ecdev) - pm_runtime_put_noidle(&pdev->dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; -err_free_tx_0: - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; -err_pm_runtime_put: - if(!tp->ecdev) - pm_runtime_put_noidle(&pdev->dev); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev->mtu); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align, gfp_t gfp) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = dma_map_single(&pdev->dev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end, gfp_t gfp) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align, gfp); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, - PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit()) - netif_err(tp, drv, dev, - "reinit failure (status = %d). Rescheduling\n", - ret); - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit()) - netif_emerg(tp, intr, dev, "Rx buffers shortage\n"); - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = dma_map_single(&tp->pci_dev->dev, addr, len, - PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = dma_map_single(&tp->pci_dev->dev, skb->data, len, - PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev) { - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - } - - return NETDEV_TX_OK; - -err_stop: - if (!tp->ecdev) - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", - pci_cmd, pci_status); - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - netif_info(tp, intr, dev, "disabling PCI DAC\n"); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - if (!tp->ecdev) - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (!skb) - goto out; - - dma_sync_single_for_cpu(&tp->pci_dev->dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -/* - * Warning : rtl8169_rx_interrupt() might be called : - * 1) from NAPI (softirq) context - * (polling = 1 : we should call netif_receive_skb()) - * 2) from process context (rtl8169_reset_task()) - * (polling = 0 : we must call netif_rx() instead) - */ -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - int polling = (budget != ~(u32)0) ? 1 : 0; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", - status); - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (tp->ecdev) { - pci_dma_sync_single_for_cpu(pdev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - - ecdev_receive(tp->ecdev, skb->data, pkt_size); - - pci_dma_sync_single_for_device(pdev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - - // No need to detect link status as - // long as frames are received: Reset watchdog. - tp->ec_watchdog_jiffies = jiffies; - } else { - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - dma_sync_single_for_device(&pdev->dev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - dma_unmap_single(&pdev->dev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { - if (likely(polling)) - netif_receive_skb(skb); - else - netif_rx(skb); - } - } - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - if (tp->ecdev) { - /* descriptors are cleaned up immediately. */ - tp->dirty_rx = tp->cur_rx; - } else { - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC); - - if (!delta && count) - netif_info(tp, intr, dev, "no Rx buffer allocated\n"); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) - netif_emerg(tp, intr, dev, "Rx buffers exhausted\n"); - } - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else - netif_info(tp, intr, dev, - "interrupt %04x in poll\n", status); - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, 100); // FIXME - rtl8169_tx_interrupt(dev, tp, tp->mmio_addr); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - if (!tp->ecdev) { - netif_stop_queue(dev); - - napi_disable(&tp->napi); - } - -core_down: - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); - - if (!tp->ecdev) - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - if(!tp->ecdev) - pm_runtime_get_sync(&pdev->dev); - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - if(!tp->ecdev) - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 4, mc_filter[1]); - RTL_W32(MAR0 + 0, mc_filter[0]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - rtl8169_net_suspend(dev); - - return 0; -} - -static void __rtl8169_resume(struct net_device *dev) -{ - netif_device_attach(dev); - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - if (netif_running(dev)) - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - tp->saved_wolopts = __rtl8169_get_wol(tp); - __rtl8169_set_wol(tp, WAKE_ANY); - spin_unlock_irq(&tp->lock); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_runtime_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - __rtl8169_set_wol(tp, tp->saved_wolopts); - tp->saved_wolopts = 0; - spin_unlock_irq(&tp->lock); - - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_idle(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - return -EBUSY; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, - .runtime_suspend = rtl8169_runtime_suspend, - .runtime_resume = rtl8169_runtime_resume, - .runtime_idle = rtl8169_runtime_idle, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.36-orig.c b/devices/r8169-2.6.36-orig.c deleted file mode 100644 index 992db2fa..00000000 --- a/devices/r8169-2.6.36-orig.c +++ /dev/null @@ -1,5024 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) readl (ioaddr + (reg)) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -/* - * we set our copybreak very high so that we don't have - * to allocate 16k frames all the time (see note in - * rtl8169_open() - */ -static int rx_copybreak = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned align; - unsigned rx_buf_sz; - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - u32 saved_wolopts; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after write - * complete indication, but before sending next command. - */ - udelay(20); -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after read - * complete indication, but before sending next command. - */ - udelay(20); - - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - /* This is to cancel a scheduled suspend if there's one. */ - pm_request_resume(&tp->pci_dev->dev); - netif_carrier_on(dev); - netif_info(tp, ifup, dev, "link up\n"); - } else { - netif_carrier_off(dev); - netif_info(tp, ifdown, dev, "link down\n"); - pm_schedule_suspend(&tp->pci_dev->dev, 100); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - u32 wolopts = 0; - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - return 0; - - options = RTL_R8(Config3); - if (options & LinkUp) - wolopts |= WAKE_PHY; - if (options & MagicPacket) - wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wolopts |= WAKE_UCAST; - if (options & BWF) - wolopts |= WAKE_BCAST; - if (options & MWF) - wolopts |= WAKE_MCAST; - - return wolopts; -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - wol->supported = WAKE_ANY; - wol->wolopts = __rtl8169_get_wol(tp); - - spin_unlock_irq(&tp->lock); -} - -static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - __rtl8169_set_wol(tp, wol->wolopts); - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - spin_unlock_irq(&tp->lock); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - netif_warn(tp, link, dev, - "incorrect speed setting refused in TBI mode\n"); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - netif_info(tp, link, dev, - "PHY does not support 1000Mbps\n"); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = dma_alloc_coherent(&tp->pci_dev->dev, sizeof(*counters), - &paddr, GFP_KERNEL); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - dma_free_coherent(&tp->pci_dev->dev, sizeof(*counters), counters, - paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - netif_warn(tp, link, dev, "PHY reset until link up\n"); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - netif_err(tp, link, dev, "PHY reset failed\n"); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if (RTL_R8(PHYstatus) & TBI_Enable) - netif_info(tp, link, dev, "TBI auto-negotiating\n"); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W32(MAC4, high); - RTL_R32(MAC4); - - RTL_W32(MAC0, low); - RTL_R32(MAC0); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | RxFIFOOver | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - netif_err(tp, probe, dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - if (pci_set_mwi(pdev) < 0) - netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n"); - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - netif_err(tp, probe, dev, - "region #%d not an MMIO resource, aborting\n", - region); - rc = -ENODEV; - goto err_out_mwi_2; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - netif_err(tp, probe, dev, - "Invalid PCI region size(s), aborting\n"); - rc = -ENODEV; - goto err_out_mwi_2; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - netif_err(tp, probe, dev, "could not request regions\n"); - goto err_out_mwi_2; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - netif_err(tp, probe, dev, "DMA configuration failed\n"); - goto err_out_free_res_3; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_3; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap) - netif_info(tp, probe, dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - netif_notice(tp, probe, dev, - "unknown MAC, using family default\n"); - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_4; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - - tp->intr_mask = 0xffff; - tp->align = cfg->align; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_4; - - pci_set_drvdata(pdev, dev); - - netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", - rtl_chip_info[tp->chipset].name, - dev->base_addr, dev->dev_addr, - (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (pci_dev_run_wake(pdev)) - pm_runtime_put_noidle(&pdev->dev); - -out: - return rc; - -err_out_msi_4: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_3: - pci_release_regions(pdev); -err_out_mwi_2: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - - if (pci_dev_run_wake(pdev)) - pm_runtime_get_noresume(&pdev->dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - unsigned int mtu) -{ - unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - - if (max_frame != 16383) - printk(KERN_WARNING PFX "WARNING! Changing of MTU on this " - "NIC may lead to frame reception errors!\n"); - - tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - pm_runtime_get_sync(&pdev->dev); - - /* - * Note that we use a magic value here, its wierd I know - * its done because, some subset of rtl8169 hardware suffers from - * a problem in which frames received that are longer than - * the size set in RxMaxSize register return garbage sizes - * when received. To avoid this we need to turn off filtering, - * which is done by setting a value of 16383 in the RxMaxSize register - * and allocating 16k frames to handle the largest possible rx value - * thats what the magic math below does. - */ - rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * dma_alloc_coherent provides more. - */ - tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr, GFP_KERNEL); - if (!tp->TxDescArray) - goto err_pm_runtime_put; - - tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr, GFP_KERNEL); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - tp->saved_wolopts = 0; - pm_runtime_put_noidle(&pdev->dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; -err_free_tx_0: - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; -err_pm_runtime_put: - pm_runtime_put_noidle(&pdev->dev); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8169_down(dev); - - rtl8169_set_rxbufsize(tp, dev->mtu); - - ret = rtl8169_init_ring(dev); - if (ret < 0) - goto out; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - -out: - return ret; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_skb(struct rtl8169_private *tp, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, - struct net_device *dev, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align, gfp_t gfp) -{ - struct sk_buff *skb; - dma_addr_t mapping; - unsigned int pad; - - pad = align ? align : NET_IP_ALIGN; - - skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp); - if (!skb) - goto err_out; - - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - - mapping = dma_map_single(&pdev->dev, skb->data, rx_buf_sz, - PCI_DMA_FROMDEVICE); - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); -out: - return skb; - -err_out: - rtl8169_make_unusable_by_asic(desc); - goto out; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } - } -} - -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end, gfp_t gfp) -{ - u32 cur; - - for (cur = start; end - cur != 0; cur++) { - struct sk_buff *skb; - unsigned int i = cur % NUM_RX_DESC; - - WARN_ON((s32)(end - cur) < 0); - - if (tp->Rx_skbuff[i]) - continue; - - skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, - tp->RxDescArray + i, - tp->rx_buf_sz, tp->align, gfp); - if (!skb) - break; - - tp->Rx_skbuff[i] = skb; - } - return cur - start; -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC) - goto err_out; - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, - PCI_DMA_TODEVICE); - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { - unsigned int entry = i % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - tp->dev->stats.tx_dropped++; - } - } - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit()) - netif_err(tp, drv, dev, - "reinit failure (status = %d). Rescheduling\n", - ret); - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit()) - netif_emerg(tp, intr, dev, "Rx buffers shortage\n"); - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = dma_map_single(&tp->pci_dev->dev, addr, len, - PCI_DMA_TODEVICE); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); - goto err_stop; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop; - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags) { - len = skb_headlen(skb); - opts1 |= FirstFrag; - } else { - len = skb->len; - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - mapping = dma_map_single(&tp->pci_dev->dev, skb->data, len, - PCI_DMA_TODEVICE); - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - - return NETDEV_TX_OK; - -err_stop: - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", - pci_cmd, pci_status); - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - netif_info(tp, intr, dev, "disabling PCI DAC\n"); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; - - rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); - - if (status & LastFrag) { - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail)) || - ((status == RxProtoIP) && !(opts1 & IPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, - struct rtl8169_private *tp, int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - bool done = false; - - if (pkt_size >= rx_copybreak) - goto out; - - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (!skb) - goto out; - - dma_sync_single_for_cpu(&tp->pci_dev->dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); - *sk_buff = skb; - done = true; -out: - return done; -} - -/* - * Warning : rtl8169_rx_interrupt() might be called : - * 1) from NAPI (softirq) context - * (polling = 1 : we should call netif_receive_skb()) - * 2) from process context (rtl8169_reset_task()) - * (polling = 0 : we must call netif_rx() instead) - */ -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count; - int polling = (budget != ~(u32)0) ? 1 : 0; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", - status); - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb = tp->Rx_skbuff[entry]; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - struct pci_dev *pdev = tp->pci_dev; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - rtl8169_rx_csum(skb, desc); - - if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - dma_sync_single_for_device(&pdev->dev, addr, - pkt_size, PCI_DMA_FROMDEVICE); - rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - } else { - dma_unmap_single(&pdev->dev, addr, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - tp->Rx_skbuff[entry] = NULL; - } - - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { - if (likely(polling)) - netif_receive_skb(skb); - else - netif_rx(skb); - } - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC); - if (!delta && count) - netif_info(tp, intr, dev, "no Rx buffer allocated\n"); - tp->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) - netif_emerg(tp, intr, dev, "Rx buffers exhausted\n"); - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver)) { - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - break; - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else - netif_info(tp, intr, dev, - "interrupt %04x in poll\n", status); - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } - - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int intrmask; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - -core_down: - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - /* - * And now for the 50k$ question: are IRQ disabled or not ? - * - * Two paths lead here: - * 1) dev->close - * -> netif_running() is available to sync the current code and the - * IRQ handler. See rtl8169_interrupt for details. - * 2) dev->change_mtu - * -> rtl8169_poll can not be issued again and re-enable the - * interruptions. Let's simply issue the IRQ down sequence again. - * - * No loop if hotpluged or major error (0xffff). - */ - intrmask = RTL_R16(IntrMask); - if (intrmask && (intrmask != 0xffff)) - goto core_down; - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - pm_runtime_get_sync(&pdev->dev); - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 4, mc_filter[1]); - RTL_W32(MAR0 + 0, mc_filter[0]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - rtl8169_net_suspend(dev); - - return 0; -} - -static void __rtl8169_resume(struct net_device *dev) -{ - netif_device_attach(dev); - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - if (netif_running(dev)) - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - tp->saved_wolopts = __rtl8169_get_wol(tp); - __rtl8169_set_wol(tp, WAKE_ANY); - spin_unlock_irq(&tp->lock); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_runtime_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - __rtl8169_set_wol(tp, tp->saved_wolopts); - tp->saved_wolopts = 0; - spin_unlock_irq(&tp->lock); - - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_idle(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - return -EBUSY; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, - .runtime_suspend = rtl8169_runtime_suspend, - .runtime_resume = rtl8169_runtime_resume, - .runtime_idle = rtl8169_runtime_idle, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.37-ethercat.c b/devices/r8169-2.6.37-ethercat.c deleted file mode 100644 index 9afe228c..00000000 --- a/devices/r8169-2.6.37-ethercat.c +++ /dev/null @@ -1,5093 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "../globals.h" -#include "ecdev.h" - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "ec_r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) readl (ioaddr + (reg)) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -/* prevent driver from being loaded automatically */ -//MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_buf_sz = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - u32 saved_wolopts; - - ec_device_t *ecdev; - unsigned long ec_watchdog_jiffies; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver (EtherCAT)"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EC_MASTER_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static void ec_poll(struct net_device *dev); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after write - * complete indication, but before sending next command. - */ - udelay(20); -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after read - * complete indication, but before sending next command. - */ - udelay(20); - - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void __rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, - bool pm) -{ - unsigned long flags; - - if (tp->ecdev) { - ecdev_set_link(tp->ecdev, tp->link_ok(ioaddr) ? 1 : 0); - return; - } - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - /* This is to cancel a scheduled suspend if there's one. */ - if (pm) - pm_request_resume(&tp->pci_dev->dev); - netif_carrier_on(dev); - if (net_ratelimit()) - netif_info(tp, ifup, dev, "link up\n"); - } else { - netif_carrier_off(dev); - netif_info(tp, ifdown, dev, "link down\n"); - if (pm) - pm_schedule_suspend(&tp->pci_dev->dev, 100); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - __rtl8169_check_link_status(dev, tp, ioaddr, false); -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - u32 wolopts = 0; - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - return 0; - - options = RTL_R8(Config3); - if (options & LinkUp) - wolopts |= WAKE_PHY; - if (options & MagicPacket) - wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wolopts |= WAKE_UCAST; - if (options & BWF) - wolopts |= WAKE_BCAST; - if (options & MWF) - wolopts |= WAKE_MCAST; - - return wolopts; -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - wol->supported = WAKE_ANY; - wol->wolopts = __rtl8169_get_wol(tp); - - spin_unlock_irq(&tp->lock); -} - -static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - __rtl8169_set_wol(tp, wol->wolopts); - spin_unlock_irq(&tp->lock); - - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - netif_warn(tp, link, dev, - "incorrect speed setting refused in TBI mode\n"); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - netif_info(tp, link, dev, - "PHY does not support 1000Mbps\n"); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - u16 vtag = swab16(opts2 & 0xffff); - - if (likely(polling)) - vlan_gro_receive(&tp->napi, vlgrp, vtag, skb); - else - __vlan_hwaccel_rx(skb, vlgrp, vtag, polling); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - struct device *d = &tp->pci_dev->dev; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - dma_free_coherent(d, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - if (!tp->ecdev) - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - netif_warn(tp, link, dev, "PHY reset until link up\n"); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - if (!tp->ecdev) - mod_timer(timer, jiffies + timeout); -out_unlock: - if (!tp->ecdev) - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->ecdev || tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - netif_err(tp, link, dev, "PHY reset failed\n"); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if (RTL_R8(PHYstatus) & TBI_Enable) - netif_info(tp, link, dev, "TBI auto-negotiating\n"); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W32(MAC4, high); - RTL_R32(MAC4); - - RTL_W32(MAC0, low); - RTL_R32(MAC0); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* disable ASPM completely as that cause random device stop working - * problems as well as full system hangs for some PCIe devices users */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - netif_err(tp, probe, dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - if (pci_set_mwi(pdev) < 0) - netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n"); - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - netif_err(tp, probe, dev, - "region #%d not an MMIO resource, aborting\n", - region); - rc = -ENODEV; - goto err_out_mwi_2; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - netif_err(tp, probe, dev, - "Invalid PCI region size(s), aborting\n"); - rc = -ENODEV; - goto err_out_mwi_2; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - netif_err(tp, probe, dev, "could not request regions\n"); - goto err_out_mwi_2; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - netif_err(tp, probe, dev, "DMA configuration failed\n"); - goto err_out_free_res_3; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_3; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap) - netif_info(tp, probe, dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - netif_notice(tp, probe, dev, - "unknown MAC, using family default\n"); - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_4; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - dev->features |= NETIF_F_GRO; - - tp->intr_mask = 0xffff; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - // offer device to EtherCAT master module - tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE); - - if (!tp->ecdev) { - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_4; - } - - pci_set_drvdata(pdev, dev); - - netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", - rtl_chip_info[tp->chipset].name, - dev->base_addr, dev->dev_addr, - (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (pci_dev_run_wake(pdev)) - pm_runtime_put_noidle(&pdev->dev); - - if (tp->ecdev) { - rc = ecdev_open(tp->ecdev); - if (rc) { - ecdev_withdraw(tp->ecdev); - goto err_out_msi_4; - } - } - else { - netif_carrier_off(dev); - } - -out: - return rc; - -err_out_msi_4: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_3: - pci_release_regions(pdev); -err_out_mwi_2: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - if (tp->ecdev) { - ecdev_close(tp->ecdev); - ecdev_withdraw(tp->ecdev); - } else { - unregister_netdev(dev); - } - - if (pci_dev_run_wake(pdev)) - pm_runtime_get_noresume(&pdev->dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - pm_runtime_get_sync(&pdev->dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * dma_alloc_coherent provides more. - */ - tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr, GFP_KERNEL); - if (!tp->TxDescArray) - goto err_pm_runtime_put; - - tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr, GFP_KERNEL); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - if (!tp->ecdev) { - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - } - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - tp->saved_wolopts = 0; - pm_runtime_put_noidle(&pdev->dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; -err_free_tx_0: - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; -err_pm_runtime_put: - pm_runtime_put_noidle(&pdev->dev); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - if (!tp->ecdev) - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11 || - tp->mac_version == RTL_GIGA_MAC_VER_22) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - if (!tp->ecdev) - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_databuff(struct rtl8169_private *tp, - void **data_buff, struct RxDesc *desc) -{ - dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz, - DMA_FROM_DEVICE); - - kfree(*data_buff); - *data_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static inline void *rtl8169_align(void *data) -{ - return (void *)ALIGN((long)data, 16); -} - -static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp, - struct RxDesc *desc) -{ - void *data; - dma_addr_t mapping; - struct device *d = &tp->pci_dev->dev; - struct net_device *dev = tp->dev; - int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; - - data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node); - if (!data) - return NULL; - - if (rtl8169_align(data) != data) { - kfree(data); - data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node); - if (!data) - return NULL; - } - - mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; - } - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); - return data; - -err_out: - kfree(data); - return NULL; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_databuff[i]) { - rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i, - tp->RxDescArray + i); - } - } -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static int rtl8169_rx_fill(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - void *data; - - if (tp->Rx_databuff[i]) - continue; - - data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i); - if (!data) { - rtl8169_make_unusable_by_asic(tp->RxDescArray + i); - goto err_out; - } - tp->Rx_databuff[i] = data; - } - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *)); - - return rtl8169_rx_fill(tp); -} - -static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); - - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start, - unsigned int n) -{ - unsigned int i; - - for (i = 0; i < n; i++) { - unsigned int entry = (start + i) % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - tp->dev->stats.tx_dropped++; - if (!tp->ecdev) - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - } - } -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit()) - netif_err(tp, drv, dev, - "reinit failure (status = %d). Rescheduling\n", - ret); - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit()) - netif_emerg(tp, intr, dev, "Rx buffers shortage\n"); - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return; - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - struct device *d = &tp->pci_dev->dev; - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; - -err_out: - rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag); - return -EIO; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - struct device *d = &tp->pci_dev->dev; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int frags; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); - goto err_stop_0; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop_0; - - len = skb_headlen(skb); - mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); - goto err_dma_0; - } - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags < 0) - goto err_dma_1; - else if (frags) - opts1 |= FirstFrag; - else { - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (!tp->ecdev && TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - - return NETDEV_TX_OK; - -err_dma_1: - rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd); -err_dma_0: - if (!tp->ecdev) - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - -err_stop_0: - if (!tp->ecdev) - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", - pci_cmd, pci_status); - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - netif_info(tp, intr, dev, "disabling PCI DAC\n"); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, - tp->TxDescArray + entry); - if (status & LastFrag) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += tx_skb->skb->len; - if (!tp->ecdev) - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (!tp->ecdev && netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) -{ - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb_checksum_none_assert(skb); -} - -static struct sk_buff *rtl8169_try_rx_copy(void *data, - struct rtl8169_private *tp, - int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - struct device *d = &tp->pci_dev->dev; - - data = rtl8169_align(data); - dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); - prefetch(data); - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (skb) - memcpy(skb->data, data, pkt_size); - dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE); - - return skb; -} - -/* - * Warning : rtl8169_rx_interrupt() might be called : - * 1) from NAPI (softirq) context - * (polling = 1 : we should call netif_receive_skb()) - * 2) from process context (rtl8169_reset_task()) - * (polling = 0 : we must call netif_rx() instead) - */ -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int count; - int polling = (budget != ~(u32)0) ? 1 : 0; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", - status); - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - if (!tp->ecdev) - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, rx_buf_sz); - } else { - struct sk_buff *skb; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, rx_buf_sz); - continue; - } - - if (tp->ecdev) { - /* reusing parts of rtl8169_try_rx_copy() */ - struct device *d = &tp->pci_dev->dev; - void *data = rtl8169_align(tp->Rx_databuff[entry]); - dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); - prefetch(data); - ecdev_receive(tp->ecdev, data, pkt_size); - dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE); - } else { - skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], - tp, pkt_size, addr); - rtl8169_mark_to_asic(desc, rx_buf_sz); - if (!skb) { - dev->stats.rx_dropped++; - continue; - } - - rtl8169_rx_csum(skb, status); - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { - if (likely(polling)) - napi_gro_receive(&tp->napi, skb); - else - netif_rx(skb); - } - } - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - tp->dirty_rx += count; - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!tp->ecdev && !netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - if (unlikely(status & RxFIFOOver)) { - switch (tp->mac_version) { - /* Work around for rx fifo overflow */ - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_26: - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - goto done; - /* Testers needed. */ - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_27: - /* Experimental science. Pktgen proof. */ - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_25: - if (status == RxFIFOOver) - goto done; - break; - default: - break; - } - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - __rtl8169_check_link_status(dev, tp, ioaddr, true); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else - netif_info(tp, intr, dev, - "interrupt %04x in poll\n", status); - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } -done: - return IRQ_RETVAL(handled); -} - -static void ec_poll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8169_interrupt(pdev->irq, dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, 100); // FIXME - rtl8169_tx_interrupt(dev, tp, tp->mmio_addr); - - if (jiffies - tp->ec_watchdog_jiffies >= 2 * HZ) { - rtl8169_phy_timer((unsigned long) dev); - tp->ec_watchdog_jiffies = jiffies; - } -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_delete_timer(dev); - - if (!tp->ecdev) { - netif_stop_queue(dev); - - napi_disable(&tp->napi); - - spin_lock_irq(&tp->lock); - } - - rtl8169_asic_down(ioaddr); - /* - * At this point device interrupts can not be enabled in any function, - * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task, - * rtl8169_reinit_task) and napi is disabled (rtl8169_poll). - */ - rtl8169_rx_missed(dev, ioaddr); - - if (!tp->ecdev) { - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - } - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - pm_runtime_get_sync(&pdev->dev); - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - if (!tp->ecdev) - free_irq(dev->irq, dev); - - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 4, mc_filter[1]); - RTL_W32(MAR0 + 0, mc_filter[0]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - rtl8169_net_suspend(dev); - - return 0; -} - -static void __rtl8169_resume(struct net_device *dev) -{ - netif_device_attach(dev); - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->ecdev) - return -EBUSY; - - rtl8169_init_phy(dev, tp); - - if (netif_running(dev)) - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - tp->saved_wolopts = __rtl8169_get_wol(tp); - __rtl8169_set_wol(tp, WAKE_ANY); - spin_unlock_irq(&tp->lock); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_runtime_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - __rtl8169_set_wol(tp, tp->saved_wolopts); - tp->saved_wolopts = 0; - spin_unlock_irq(&tp->lock); - - rtl8169_init_phy(dev, tp); - - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_idle(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->TxDescArray ? -EBUSY : 0; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, - .runtime_suspend = rtl8169_runtime_suspend, - .runtime_resume = rtl8169_runtime_resume, - .runtime_idle = rtl8169_runtime_idle, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); diff --git a/devices/r8169-2.6.37-orig.c b/devices/r8169-2.6.37-orig.c deleted file mode 100644 index b17e356d..00000000 --- a/devices/r8169-2.6.37-orig.c +++ /dev/null @@ -1,5008 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) readl (ioaddr + (reg)) - -enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b // 8168DP -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_buf_sz = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - int chipset; - int mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - struct timer_list timer; - u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; - int phy_1000_ctrl_reg; -#ifdef CONFIG_R8169_VLAN - struct vlan_group *vlgrp; -#endif - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(void __iomem *); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(void __iomem *); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - int pcie_cap; - struct delayed_work task; - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - u32 saved_wolopts; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); - -static int rtl8169_open(struct net_device *dev); -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); -static void rtl8169_rx_clear(struct rtl8169_private *tp); -static int rtl8169_poll(struct napi_struct *napi, int budget); - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after write - * complete indication, but before sending next command. - */ - udelay(20); -} - -static int mdio_read(void __iomem *ioaddr, int reg_addr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - /* - * According to hardware specs a 20us delay is required after read - * complete indication, but before sending next command. - */ - udelay(20); - - return value; -} - -static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) -{ - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m) -{ - int val; - - val = mdio_read(ioaddr, reg_addr); - mdio_write(ioaddr, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - mdio_write(ioaddr, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - return mdio_read(ioaddr, location); -} - -static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) -{ - unsigned int i; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void __iomem *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) -{ - u8 value = 0xff; - unsigned int i; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - for (i = 0; i < 300; i++) { - if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) { - value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK; - break; - } - udelay(100); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) -{ - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static void rtl8169_asic_down(void __iomem *ioaddr) -{ - RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); - RTL_R16(CPlusCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) -{ - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void __iomem *ioaddr) -{ - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) -{ - unsigned int val; - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static void __rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, - bool pm) -{ - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (tp->link_ok(ioaddr)) { - /* This is to cancel a scheduled suspend if there's one. */ - if (pm) - pm_request_resume(&tp->pci_dev->dev); - netif_carrier_on(dev); - if (net_ratelimit()) - netif_info(tp, ifup, dev, "link up\n"); - } else { - netif_carrier_off(dev); - netif_info(tp, ifdown, dev, "link down\n"); - if (pm) - pm_schedule_suspend(&tp->pci_dev->dev, 100); - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - __rtl8169_check_link_status(dev, tp, ioaddr, false); -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - u32 wolopts = 0; - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - return 0; - - options = RTL_R8(Config3); - if (options & LinkUp) - wolopts |= WAKE_PHY; - if (options & MagicPacket) - wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wolopts |= WAKE_UCAST; - if (options & BWF) - wolopts |= WAKE_BCAST; - if (options & MWF) - wolopts |= WAKE_MCAST; - - return wolopts; -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - wol->supported = WAKE_ANY; - wol->wolopts = __rtl8169_get_wol(tp); - - spin_unlock_irq(&tp->lock); -} - -static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - spin_lock_irq(&tp->lock); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - __rtl8169_set_wol(tp, wol->wolopts); - spin_unlock_irq(&tp->lock); - - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - return 0; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8169_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - netif_warn(tp, link, dev, - "incorrect speed setting refused in TBI mode\n"); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int giga_ctrl, bmcr; - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16)) { - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - netif_info(tp, link, dev, - "PHY does not support 1000Mbps\n"); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII - * registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - return -EINVAL; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - mdio_write(ioaddr, 0x1f, 0x0000); - } - - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_BMCR, bmcr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - mdio_write(ioaddr, 0x17, 0x2138); - mdio_write(ioaddr, 0x0e, 0x0260); - } else { - mdio_write(ioaddr, 0x17, 0x2108); - mdio_write(ioaddr, 0x0e, 0x0000); - } - } - - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 rtl8169_get_rx_csum(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->cp_cmd & RxChkSum; -} - -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#ifdef CONFIG_R8169_VLAN - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return (vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - /* - * Do not disable RxVlan on 8110SCd. - */ - if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - struct vlan_group *vlgrp = tp->vlgrp; - int ret; - - if (vlgrp && (opts2 & RxVlanTag)) { - u16 vtag = swab16(opts2 & 0xffff); - - if (likely(polling)) - vlan_gro_receive(&tp->napi, vlgrp, vtag, skb); - else - __vlan_hwaccel_rx(skb, vlgrp, vtag, polling); - ret = 0; - } else - ret = -1; - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8169_VLAN */ - -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb, int polling) -{ - return -1; -} - -#endif - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - cmd->speed = SPEED_1000; - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - int rc; - - spin_lock_irqsave(&tp->lock, flags); - - rc = tp->get_settings(dev, cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - spin_lock_irqsave(&tp->lock, flags); - memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - int wait = 1000; - struct device *d = &tp->pci_dev->dev; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - while (wait--) { - if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ - memcpy(&tp->counters, counters, sizeof(*counters)); - break; - } - udelay(10); - } - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - dma_free_coherent(d, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 vendor_id, device_id; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id); - - if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000)) - return; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x10, 0xf01b); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp, ioaddr); -} - -static void rtl8169sce_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) -{ - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_2[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaef }, - { 0x06, 0x59ee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d59 }, - { 0x06, 0x0fef }, - { 0x06, 0x0139 }, - { 0x06, 0x029e }, - { 0x06, 0x06ef }, - { 0x06, 0x1039 }, - { 0x06, 0x089f }, - { 0x06, 0x2aee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x01e0 }, - { 0x06, 0xf87c }, - { 0x06, 0xe1f8 }, - { 0x06, 0x7d58 }, - { 0x06, 0x409e }, - { 0x06, 0x0f39 }, - { 0x06, 0x46aa }, - { 0x06, 0x0bbf }, - { 0x06, 0x8290 }, - { 0x06, 0xd682 }, - { 0x06, 0x9802 }, - { 0x06, 0x014f }, - { 0x06, 0xae09 }, - { 0x06, 0xbf82 }, - { 0x06, 0x98d6 }, - { 0x06, 0x82a0 }, - { 0x06, 0x0201 }, - { 0x06, 0x4fef }, - { 0x06, 0x95fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xeef8 }, - { 0x06, 0xea00 }, - { 0x06, 0xeef8 }, - { 0x06, 0xeb00 }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7ce3 }, - { 0x06, 0xf87d }, - { 0x06, 0xa511 }, - { 0x06, 0x1112 }, - { 0x06, 0xd240 }, - { 0x06, 0xd644 }, - { 0x06, 0x4402 }, - { 0x06, 0x8217 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6aa }, - { 0x06, 0xaa02 }, - { 0x06, 0x8217 }, - { 0x06, 0xae0f }, - { 0x06, 0xa544 }, - { 0x06, 0x4402 }, - { 0x06, 0xae4d }, - { 0x06, 0xa5aa }, - { 0x06, 0xaa02 }, - { 0x06, 0xae47 }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x834e }, - { 0x06, 0x00ee }, - { 0x06, 0x834d }, - { 0x06, 0x0fee }, - { 0x06, 0x834c }, - { 0x06, 0x0fee }, - { 0x06, 0x834f }, - { 0x06, 0x00ee }, - { 0x06, 0x8351 }, - { 0x06, 0x00ee }, - { 0x06, 0x834a }, - { 0x06, 0xffee }, - { 0x06, 0x834b }, - { 0x06, 0xffe0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3158 }, - { 0x06, 0xfee4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8be0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xaf82 }, - { 0x06, 0x13e0 }, - { 0x06, 0x834f }, - { 0x06, 0x10e4 }, - { 0x06, 0x834f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x009f }, - { 0x06, 0x0ae0 }, - { 0x06, 0x834f }, - { 0x06, 0xa010 }, - { 0x06, 0xa5ee }, - { 0x06, 0x834e }, - { 0x06, 0x01e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7805 }, - { 0x06, 0x9e9a }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x10e0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0f }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x019e }, - { 0x06, 0x05ae }, - { 0x06, 0x0caf }, - { 0x06, 0x81f8 }, - { 0x06, 0xaf81 }, - { 0x06, 0xa3af }, - { 0x06, 0x81dc }, - { 0x06, 0xaf82 }, - { 0x06, 0x13ee }, - { 0x06, 0x8348 }, - { 0x06, 0x00ee }, - { 0x06, 0x8349 }, - { 0x06, 0x00e0 }, - { 0x06, 0x8351 }, - { 0x06, 0x10e4 }, - { 0x06, 0x8351 }, - { 0x06, 0x5801 }, - { 0x06, 0x9fea }, - { 0x06, 0xd000 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xe2f8 }, - { 0x06, 0xeae3 }, - { 0x06, 0xf8eb }, - { 0x06, 0x5af8 }, - { 0x06, 0x1e20 }, - { 0x06, 0xe6f8 }, - { 0x06, 0xeae5 }, - { 0x06, 0xf8eb }, - { 0x06, 0xd302 }, - { 0x06, 0xb3fe }, - { 0x06, 0xe2f8 }, - { 0x06, 0x7cef }, - { 0x06, 0x325b }, - { 0x06, 0x80e3 }, - { 0x06, 0xf87d }, - { 0x06, 0x9e03 }, - { 0x06, 0x7dff }, - { 0x06, 0xff0d }, - { 0x06, 0x581c }, - { 0x06, 0x551a }, - { 0x06, 0x6511 }, - { 0x06, 0xa190 }, - { 0x06, 0xd3e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x491b }, - { 0x06, 0x56ab }, - { 0x06, 0x08ef }, - { 0x06, 0x56e6 }, - { 0x06, 0x8348 }, - { 0x06, 0xe783 }, - { 0x06, 0x4910 }, - { 0x06, 0xd180 }, - { 0x06, 0x1f66 }, - { 0x06, 0xa004 }, - { 0x06, 0xb9e2 }, - { 0x06, 0x8348 }, - { 0x06, 0xe383 }, - { 0x06, 0x49ef }, - { 0x06, 0x65e2 }, - { 0x06, 0x834a }, - { 0x06, 0xe383 }, - { 0x06, 0x4b1b }, - { 0x06, 0x56aa }, - { 0x06, 0x0eef }, - { 0x06, 0x56e6 }, - { 0x06, 0x834a }, - { 0x06, 0xe783 }, - { 0x06, 0x4be2 }, - { 0x06, 0x834d }, - { 0x06, 0xe683 }, - { 0x06, 0x4ce0 }, - { 0x06, 0x834d }, - { 0x06, 0xa000 }, - { 0x06, 0x0caf }, - { 0x06, 0x81dc }, - { 0x06, 0xe083 }, - { 0x06, 0x4d10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4dae }, - { 0x06, 0x0480 }, - { 0x06, 0xe483 }, - { 0x06, 0x4de0 }, - { 0x06, 0x834e }, - { 0x06, 0x7803 }, - { 0x06, 0x9e0b }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x049e }, - { 0x06, 0x04ee }, - { 0x06, 0x834e }, - { 0x06, 0x02e0 }, - { 0x06, 0x8332 }, - { 0x06, 0xe183 }, - { 0x06, 0x3359 }, - { 0x06, 0x0fe2 }, - { 0x06, 0x834d }, - { 0x06, 0x0c24 }, - { 0x06, 0x5af0 }, - { 0x06, 0x1e12 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ce5 }, - { 0x06, 0xf88d }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x6801 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xae37 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e03 }, - { 0x06, 0xe083 }, - { 0x06, 0x4ce1 }, - { 0x06, 0x834d }, - { 0x06, 0x1b01 }, - { 0x06, 0x9e04 }, - { 0x06, 0xaaa1 }, - { 0x06, 0xaea8 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xaeab }, - { 0x06, 0xe083 }, - { 0x06, 0x4f78 }, - { 0x06, 0x039f }, - { 0x06, 0x14ee }, - { 0x06, 0x834e }, - { 0x06, 0x05d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x5554 }, - { 0x06, 0x0282 }, - { 0x06, 0x17d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xba00 }, - { 0x06, 0x0282 }, - { 0x06, 0x17fe }, - { 0x06, 0xfdfc }, - { 0x06, 0x05f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x6802 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x580f }, - { 0x06, 0x1e02 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xd000 }, - { 0x06, 0x0282 }, - { 0x06, 0x5bbf }, - { 0x06, 0x8350 }, - { 0x06, 0xef46 }, - { 0x06, 0xdc19 }, - { 0x06, 0xddd0 }, - { 0x06, 0x0102 }, - { 0x06, 0x825b }, - { 0x06, 0x0282 }, - { 0x06, 0x77e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6158 }, - { 0x06, 0xfde4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61fc }, - { 0x06, 0x04f9 }, - { 0x06, 0xfafb }, - { 0x06, 0xc6bf }, - { 0x06, 0xf840 }, - { 0x06, 0xbe83 }, - { 0x06, 0x50a0 }, - { 0x06, 0x0101 }, - { 0x06, 0x071b }, - { 0x06, 0x89cf }, - { 0x06, 0xd208 }, - { 0x06, 0xebdb }, - { 0x06, 0x19b2 }, - { 0x06, 0xfbff }, - { 0x06, 0xfefd }, - { 0x06, 0x04f8 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x48e1 }, - { 0x06, 0xf849 }, - { 0x06, 0x6808 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0x58f7 }, - { 0x06, 0xe4f8 }, - { 0x06, 0x48e5 }, - { 0x06, 0xf849 }, - { 0x06, 0xfc04 }, - { 0x06, 0x4d20 }, - { 0x06, 0x0002 }, - { 0x06, 0x4e22 }, - { 0x06, 0x0002 }, - { 0x06, 0x4ddf }, - { 0x06, 0xff01 }, - { 0x06, 0x4edd }, - { 0x06, 0xff01 }, - { 0x05, 0x83d4 }, - { 0x06, 0x8000 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8051 }, - { 0x02, 0x6010 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef); - mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0d, 0x0300); - mdio_patch(ioaddr, 0x0f, 0x0010); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2)); -} - -static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 } - }; - static const struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8000 }, - { 0x06, 0xf8f9 }, - { 0x06, 0xfaee }, - { 0x06, 0xf8ea }, - { 0x06, 0x00ee }, - { 0x06, 0xf8eb }, - { 0x06, 0x00e2 }, - { 0x06, 0xf87c }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7da5 }, - { 0x06, 0x1111 }, - { 0x06, 0x12d2 }, - { 0x06, 0x40d6 }, - { 0x06, 0x4444 }, - { 0x06, 0x0281 }, - { 0x06, 0xc6d2 }, - { 0x06, 0xa0d6 }, - { 0x06, 0xaaaa }, - { 0x06, 0x0281 }, - { 0x06, 0xc6ae }, - { 0x06, 0x0fa5 }, - { 0x06, 0x4444 }, - { 0x06, 0x02ae }, - { 0x06, 0x4da5 }, - { 0x06, 0xaaaa }, - { 0x06, 0x02ae }, - { 0x06, 0x47af }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e00 }, - { 0x06, 0xee83 }, - { 0x06, 0x4d0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4c0f }, - { 0x06, 0xee83 }, - { 0x06, 0x4f00 }, - { 0x06, 0xee83 }, - { 0x06, 0x5100 }, - { 0x06, 0xee83 }, - { 0x06, 0x4aff }, - { 0x06, 0xee83 }, - { 0x06, 0x4bff }, - { 0x06, 0xe083 }, - { 0x06, 0x30e1 }, - { 0x06, 0x8331 }, - { 0x06, 0x58fe }, - { 0x06, 0xe4f8 }, - { 0x06, 0x8ae5 }, - { 0x06, 0xf88b }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8daf }, - { 0x06, 0x81c2 }, - { 0x06, 0xe083 }, - { 0x06, 0x4f10 }, - { 0x06, 0xe483 }, - { 0x06, 0x4fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7800 }, - { 0x06, 0x9f0a }, - { 0x06, 0xe083 }, - { 0x06, 0x4fa0 }, - { 0x06, 0x10a5 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e01 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x059e }, - { 0x06, 0x9ae0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e10 }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0fe0 }, - { 0x06, 0x834e }, - { 0x06, 0x7801 }, - { 0x06, 0x9e05 }, - { 0x06, 0xae0c }, - { 0x06, 0xaf81 }, - { 0x06, 0xa7af }, - { 0x06, 0x8152 }, - { 0x06, 0xaf81 }, - { 0x06, 0x8baf }, - { 0x06, 0x81c2 }, - { 0x06, 0xee83 }, - { 0x06, 0x4800 }, - { 0x06, 0xee83 }, - { 0x06, 0x4900 }, - { 0x06, 0xe083 }, - { 0x06, 0x5110 }, - { 0x06, 0xe483 }, - { 0x06, 0x5158 }, - { 0x06, 0x019f }, - { 0x06, 0xead0 }, - { 0x06, 0x00d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66e2 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe3f8 }, - { 0x06, 0xeb5a }, - { 0x06, 0xf81e }, - { 0x06, 0x20e6 }, - { 0x06, 0xf8ea }, - { 0x06, 0xe5f8 }, - { 0x06, 0xebd3 }, - { 0x06, 0x02b3 }, - { 0x06, 0xfee2 }, - { 0x06, 0xf87c }, - { 0x06, 0xef32 }, - { 0x06, 0x5b80 }, - { 0x06, 0xe3f8 }, - { 0x06, 0x7d9e }, - { 0x06, 0x037d }, - { 0x06, 0xffff }, - { 0x06, 0x0d58 }, - { 0x06, 0x1c55 }, - { 0x06, 0x1a65 }, - { 0x06, 0x11a1 }, - { 0x06, 0x90d3 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0x1b56 }, - { 0x06, 0xab08 }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x48e7 }, - { 0x06, 0x8349 }, - { 0x06, 0x10d1 }, - { 0x06, 0x801f }, - { 0x06, 0x66a0 }, - { 0x06, 0x04b9 }, - { 0x06, 0xe283 }, - { 0x06, 0x48e3 }, - { 0x06, 0x8349 }, - { 0x06, 0xef65 }, - { 0x06, 0xe283 }, - { 0x06, 0x4ae3 }, - { 0x06, 0x834b }, - { 0x06, 0x1b56 }, - { 0x06, 0xaa0e }, - { 0x06, 0xef56 }, - { 0x06, 0xe683 }, - { 0x06, 0x4ae7 }, - { 0x06, 0x834b }, - { 0x06, 0xe283 }, - { 0x06, 0x4de6 }, - { 0x06, 0x834c }, - { 0x06, 0xe083 }, - { 0x06, 0x4da0 }, - { 0x06, 0x000c }, - { 0x06, 0xaf81 }, - { 0x06, 0x8be0 }, - { 0x06, 0x834d }, - { 0x06, 0x10e4 }, - { 0x06, 0x834d }, - { 0x06, 0xae04 }, - { 0x06, 0x80e4 }, - { 0x06, 0x834d }, - { 0x06, 0xe083 }, - { 0x06, 0x4e78 }, - { 0x06, 0x039e }, - { 0x06, 0x0be0 }, - { 0x06, 0x834e }, - { 0x06, 0x7804 }, - { 0x06, 0x9e04 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e02 }, - { 0x06, 0xe083 }, - { 0x06, 0x32e1 }, - { 0x06, 0x8333 }, - { 0x06, 0x590f }, - { 0x06, 0xe283 }, - { 0x06, 0x4d0c }, - { 0x06, 0x245a }, - { 0x06, 0xf01e }, - { 0x06, 0x12e4 }, - { 0x06, 0xf88c }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8de0 }, - { 0x06, 0x8330 }, - { 0x06, 0xe183 }, - { 0x06, 0x3168 }, - { 0x06, 0x01e4 }, - { 0x06, 0xf88a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x8bae }, - { 0x06, 0x37ee }, - { 0x06, 0x834e }, - { 0x06, 0x03e0 }, - { 0x06, 0x834c }, - { 0x06, 0xe183 }, - { 0x06, 0x4d1b }, - { 0x06, 0x019e }, - { 0x06, 0x04aa }, - { 0x06, 0xa1ae }, - { 0x06, 0xa8ee }, - { 0x06, 0x834e }, - { 0x06, 0x04ee }, - { 0x06, 0x834f }, - { 0x06, 0x00ae }, - { 0x06, 0xabe0 }, - { 0x06, 0x834f }, - { 0x06, 0x7803 }, - { 0x06, 0x9f14 }, - { 0x06, 0xee83 }, - { 0x06, 0x4e05 }, - { 0x06, 0xd240 }, - { 0x06, 0xd655 }, - { 0x06, 0x5402 }, - { 0x06, 0x81c6 }, - { 0x06, 0xd2a0 }, - { 0x06, 0xd6ba }, - { 0x06, 0x0002 }, - { 0x06, 0x81c6 }, - { 0x06, 0xfefd }, - { 0x06, 0xfc05 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf860 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x6168 }, - { 0x06, 0x02e4 }, - { 0x06, 0xf860 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x61e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4958 }, - { 0x06, 0x0f1e }, - { 0x06, 0x02e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49d0 }, - { 0x06, 0x0002 }, - { 0x06, 0x820a }, - { 0x06, 0xbf83 }, - { 0x06, 0x50ef }, - { 0x06, 0x46dc }, - { 0x06, 0x19dd }, - { 0x06, 0xd001 }, - { 0x06, 0x0282 }, - { 0x06, 0x0a02 }, - { 0x06, 0x8226 }, - { 0x06, 0xe0f8 }, - { 0x06, 0x60e1 }, - { 0x06, 0xf861 }, - { 0x06, 0x58fd }, - { 0x06, 0xe4f8 }, - { 0x06, 0x60e5 }, - { 0x06, 0xf861 }, - { 0x06, 0xfc04 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbc6 }, - { 0x06, 0xbff8 }, - { 0x06, 0x40be }, - { 0x06, 0x8350 }, - { 0x06, 0xa001 }, - { 0x06, 0x0107 }, - { 0x06, 0x1b89 }, - { 0x06, 0xcfd2 }, - { 0x06, 0x08eb }, - { 0x06, 0xdb19 }, - { 0x06, 0xb2fb }, - { 0x06, 0xfffe }, - { 0x06, 0xfd04 }, - { 0x06, 0xf8e0 }, - { 0x06, 0xf848 }, - { 0x06, 0xe1f8 }, - { 0x06, 0x4968 }, - { 0x06, 0x08e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x4958 }, - { 0x06, 0xf7e4 }, - { 0x06, 0xf848 }, - { 0x06, 0xe5f8 }, - { 0x06, 0x49fc }, - { 0x06, 0x044d }, - { 0x06, 0x2000 }, - { 0x06, 0x024e }, - { 0x06, 0x2200 }, - { 0x06, 0x024d }, - { 0x06, 0xdfff }, - { 0x06, 0x014e }, - { 0x06, 0xddff }, - { 0x06, 0x0100 }, - { 0x05, 0x83d8 }, - { 0x06, 0x8000 }, - { 0x03, 0xdc00 }, - { 0x05, 0xfff6 }, - { 0x06, 0x00fc }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = mdio_read(ioaddr, 0x0d); - if ((val & 0x00ff) != 0x006c) { - u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - mdio_write(ioaddr, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - mdio_write(ioaddr, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600); - mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000); - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_write(ioaddr, 0x17, 0x0cc0); - - mdio_write(ioaddr, 0x1f, 0x0002); - mdio_patch(ioaddr, 0x0f, 0x0017); - - rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1)); -} - -static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - mdio_patch(ioaddr, 0x10, 1 << 15); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp, ioaddr); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - - spin_lock_irq(&tp->lock); - - if (tp->phy_reset_pending(ioaddr)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - goto out_unlock; - - netif_warn(tp, link, dev, "PHY reset until link up\n"); - - tp->phy_reset_enable(ioaddr); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); -} - -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); -} -#endif - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - msleep(1); - } - netif_err(tp, link, dev, "PHY reset failed\n"); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if (RTL_R8(PHYstatus) & TBI_Enable) - netif_info(tp, link, dev, "TBI auto-negotiating\n"); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); - - spin_lock_irq(&tp->lock); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W32(MAC4, high); - RTL_R32(MAC4); - - RTL_W32(MAC0, low); - RTL_R32(MAC0); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - spin_unlock_irq(&tp->lock); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, - const struct rtl_cfg_info *cfg) -{ - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - RTL_W8(Config2, cfg2); - return msi; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static const struct net_device_ops rtl8169_netdev_ops = { - .ndo_open = rtl8169_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats = rtl8169_get_stats, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_multicast_list = rtl_set_rx_mode, -#ifdef CONFIG_R8169_VLAN - .ndo_vlan_rx_register = rtl8169_vlan_rx_register, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - unsigned int i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl8169_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* disable ASPM completely as that cause random device stop working - * problems as well as full system hangs for some PCIe devices users */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - netif_err(tp, probe, dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - if (pci_set_mwi(pdev) < 0) - netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n"); - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - netif_err(tp, probe, dev, - "region #%d not an MMIO resource, aborting\n", - region); - rc = -ENODEV; - goto err_out_mwi_2; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - netif_err(tp, probe, dev, - "Invalid PCI region size(s), aborting\n"); - rc = -ENODEV; - goto err_out_mwi_2; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - netif_err(tp, probe, dev, "could not request regions\n"); - goto err_out_mwi_2; - } - - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - netif_err(tp, probe, dev, "DMA configuration failed\n"); - goto err_out_free_res_3; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_3; - } - - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap) - netif_info(tp, probe, dev, "no PCI Express capability\n"); - - RTL_W16(IntrMask, 0x0000); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - RTL_W16(IntrStatus, 0xffff); - - pci_set_master(pdev); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); - - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - netif_notice(tp, probe, dev, - "unknown MAC, using family default\n"); - tp->mac_version = cfg->default_ver; - } - - rtl8169_print_mac_version(tp); - - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_4; - } - tp->chipset = i; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - spin_lock_init(&tp->lock); - - tp->mmio_addr = ioaddr; - - /* Get MAC address */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - -#ifdef CONFIG_R8169_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif - dev->features |= NETIF_F_GRO; - - tp->intr_mask = 0xffff; - tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_4; - - pci_set_drvdata(pdev, dev); - - netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", - rtl_chip_info[tp->chipset].name, - dev->base_addr, dev->dev_addr, - (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); - - rtl8169_init_phy(dev, tp); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (pci_dev_run_wake(pdev)) - pm_runtime_put_noidle(&pdev->dev); - - netif_carrier_off(dev); - -out: - return rc; - -err_out_msi_4: - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_3: - pci_release_regions(pdev); -err_out_mwi_2: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static void __devexit rtl8169_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - flush_scheduled_work(); - - unregister_netdev(dev); - - if (pci_dev_run_wake(pdev)) - pm_runtime_get_noresume(&pdev->dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static int rtl8169_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - pm_runtime_get_sync(&pdev->dev); - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * dma_alloc_coherent provides more. - */ - tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr, GFP_KERNEL); - if (!tp->TxDescArray) - goto err_pm_runtime_put; - - tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr, GFP_KERNEL); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_DELAYED_WORK(&tp->task, NULL); - - smp_mb(); - - retval = request_irq(dev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_ring_2; - - napi_enable(&tp->napi); - - rtl_hw_start(dev); - - rtl8169_request_timer(dev); - - tp->saved_wolopts = 0; - pm_runtime_put_noidle(&pdev->dev); - - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -out: - return retval; - -err_release_ring_2: - rtl8169_rx_clear(tp); -err_free_rx_1: - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; -err_free_tx_0: - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; -err_pm_runtime_put: - pm_runtime_put_noidle(&pdev->dev); - goto out; -} - -static void rtl8169_hw_reset(void __iomem *ioaddr) -{ - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } - - tp->hw_start(dev); - - netif_start_queue(dev); -} - - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void __iomem *ioaddr) -{ - u32 csi; - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) -{ - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11 || - tp->mac_version == RTL_GIGA_MAC_VER_22) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) -{ - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) -{ - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_databuff(struct rtl8169_private *tp, - void **data_buff, struct RxDesc *desc) -{ - dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz, - DMA_FROM_DEVICE); - - kfree(*data_buff); - *data_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static inline void *rtl8169_align(void *data) -{ - return (void *)ALIGN((long)data, 16); -} - -static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp, - struct RxDesc *desc) -{ - void *data; - dma_addr_t mapping; - struct device *d = &tp->pci_dev->dev; - struct net_device *dev = tp->dev; - int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; - - data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node); - if (!data) - return NULL; - - if (rtl8169_align(data) != data) { - kfree(data); - data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node); - if (!data) - return NULL; - } - - mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; - } - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); - return data; - -err_out: - kfree(data); - return NULL; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_databuff[i]) { - rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i, - tp->RxDescArray + i); - } - } -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static int rtl8169_rx_fill(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - void *data; - - if (tp->Rx_databuff[i]) - continue; - - data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i); - if (!data) { - rtl8169_make_unusable_by_asic(tp->RxDescArray + i); - goto err_out; - } - tp->Rx_databuff[i] = data; - } - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *)); - - return rtl8169_rx_fill(tp); -} - -static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); - - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start, - unsigned int n) -{ - unsigned int i; - - for (i = 0; i < n; i++) { - unsigned int entry = (start + i) % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - tp->dev->stats.tx_dropped++; - dev_kfree_skb(skb); - tx_skb->skb = NULL; - } - } - } -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(ioaddr); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit()) - netif_err(tp, drv, dev, - "reinit failure (status = %d). Rescheduling\n", - ret); - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); - rtl8169_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit()) - netif_emerg(tp, intr, dev, "Rx buffers shortage\n"); - rtl8169_schedule_work(dev, rtl8169_reset_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp->mmio_addr); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - struct device *d = &tp->pci_dev->dev; - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; - -err_out: - rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag); - return -EIO; -} - -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) -{ - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; - else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ - } - return 0; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - struct device *d = &tp->pci_dev->dev; - dma_addr_t mapping; - u32 status, len; - u32 opts1; - int frags; - - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); - goto err_stop_0; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop_0; - - len = skb_headlen(skb); - mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); - goto err_dma_0; - } - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); - - frags = rtl8169_xmit_frags(tp, skb, opts1); - if (frags < 0) - goto err_dma_1; - else if (frags) - opts1 |= FirstFrag; - else { - opts1 |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - wmb(); - - /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - wmb(); - - RTL_W8(TxPoll, NPQ); /* set polling bit */ - - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { - netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) - netif_wake_queue(dev); - } - - return NETDEV_TX_OK; - -err_dma_1: - rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd); -err_dma_0: - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - -err_stop_0: - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - void __iomem *ioaddr = tp->mmio_addr; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", - pci_cmd, pci_status); - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - netif_info(tp, intr, dev, "disabling PCI DAC\n"); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(ioaddr); - - rtl8169_schedule_work(dev, rtl8169_reinit_task); -} - -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, - tp->TxDescArray + entry); - if (status & LastFrag) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += tx_skb->skb->len; - dev_kfree_skb(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) -{ - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb_checksum_none_assert(skb); -} - -static struct sk_buff *rtl8169_try_rx_copy(void *data, - struct rtl8169_private *tp, - int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - struct device *d = &tp->pci_dev->dev; - - data = rtl8169_align(data); - dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); - prefetch(data); - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (skb) - memcpy(skb->data, data, pkt_size); - dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE); - - return skb; -} - -/* - * Warning : rtl8169_rx_interrupt() might be called : - * 1) from NAPI (softirq) context - * (polling = 1 : we should call netif_receive_skb()) - * 2) from process context (rtl8169_reset_task()) - * (polling = 0 : we must call netif_rx() instead) - */ -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int count; - int polling = (budget != ~(u32)0) ? 1 : 0; - - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = min(rx_left, budget); - - for (; rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1); - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", - status); - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; - } - rtl8169_mark_to_asic(desc, rx_buf_sz); - } else { - struct sk_buff *skb; - dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, rx_buf_sz); - continue; - } - - skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], - tp, pkt_size, addr); - rtl8169_mark_to_asic(desc, rx_buf_sz); - if (!skb) { - dev->stats.rx_dropped++; - continue; - } - - rtl8169_rx_csum(skb, status); - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { - if (likely(polling)) - napi_gro_receive(&tp->napi, skb); - else - netif_rx(skb); - } - - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; - } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - tp->dirty_rx += count; - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int handled = 0; - int status; - - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - handled = 1; - - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); - break; - } - - if (unlikely(status & RxFIFOOver)) { - switch (tp->mac_version) { - /* Work around for rx fifo overflow */ - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_26: - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - goto done; - /* Testers needed. */ - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_27: - /* Experimental science. Pktgen proof. */ - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_25: - if (status == RxFIFOOver) - goto done; - break; - default: - break; - } - } - - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } - - if (status & LinkChg) - __rtl8169_check_link_status(dev, tp, ioaddr, true); - - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else - netif_info(tp, intr, dev, - "interrupt %04x in poll\n", status); - } - - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); - } -done: - return IRQ_RETVAL(handled); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; - - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); - - if (work_done < budget) { - napi_complete(napi); - - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - wmb(); - RTL_W16(IntrMask, tp->intr_event); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_delete_timer(dev); - - netif_stop_queue(dev); - - napi_disable(&tp->napi); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - /* - * At this point device interrupts can not be enabled in any function, - * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task, - * rtl8169_reinit_task) and napi is disabled (rtl8169_poll). - */ - rtl8169_rx_missed(dev, ioaddr); - - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - pm_runtime_get_sync(&pdev->dev); - - /* update counters before going down */ - rtl8169_update_counters(dev); - - rtl8169_down(dev); - - free_irq(dev->irq, dev); - - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - spin_lock_irqsave(&tp->lock, flags); - - tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - RTL_W32(MAR0 + 4, mc_filter[1]); - RTL_W32(MAR0 + 0, mc_filter[0]); - - RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &dev->stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - rtl8169_net_suspend(dev); - - return 0; -} - -static void __rtl8169_resume(struct net_device *dev) -{ - netif_device_attach(dev); - rtl8169_schedule_work(dev, rtl8169_reset_task); -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_phy(dev, tp); - - if (netif_running(dev)) - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - tp->saved_wolopts = __rtl8169_get_wol(tp); - __rtl8169_set_wol(tp, WAKE_ANY); - spin_unlock_irq(&tp->lock); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_runtime_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - spin_lock_irq(&tp->lock); - __rtl8169_set_wol(tp, tp->saved_wolopts); - tp->saved_wolopts = 0; - spin_unlock_irq(&tp->lock); - - rtl8169_init_phy(dev, tp); - - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_idle(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->TxDescArray ? -EBUSY : 0; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, - .runtime_suspend = rtl8169_runtime_suspend, - .runtime_resume = rtl8169_runtime_resume, - .runtime_idle = rtl8169_runtime_idle, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8169_net_suspend(dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - spin_lock_irq(&tp->lock); - - rtl8169_asic_down(ioaddr); - - spin_unlock_irq(&tp->lock); - - if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { - pci_clear_master(pdev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module);