diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2002-08-02 20:13:18 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-08-02 20:13:18 -0700 |
| commit | 3334a8ca9896ca4d4ed5bd12a75aa139efcb3b56 (patch) | |
| tree | 8e57e8d305a8b3ecba240c83f841bf75cef9e257 | |
| parent | 95c26f5af55e9efbc36084e7a3de07dd050f878b (diff) | |
| parent | 67c5f644e47fe9576abbc036fb22735aa80a85f1 (diff) | |
Merge http://gkernel.bkbits.net/net-drivers-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
| -rw-r--r-- | Documentation/networking/e1000.txt | 26 | ||||
| -rw-r--r-- | drivers/net/8139cp.c | 62 | ||||
| -rw-r--r-- | drivers/net/e100/e100.h | 48 | ||||
| -rw-r--r-- | drivers/net/e100/e100_config.c | 85 | ||||
| -rw-r--r-- | drivers/net/e100/e100_config.h | 2 | ||||
| -rw-r--r-- | drivers/net/e100/e100_eeprom.c | 3 | ||||
| -rw-r--r-- | drivers/net/e100/e100_main.c | 550 | ||||
| -rw-r--r-- | drivers/net/e100/e100_phy.c | 47 | ||||
| -rw-r--r-- | drivers/net/e100/e100_phy.h | 21 | ||||
| -rw-r--r-- | drivers/net/e100/e100_proc.c | 413 | ||||
| -rw-r--r-- | drivers/net/e100/e100_test.c | 9 | ||||
| -rw-r--r-- | drivers/net/e100/e100_vendor.h | 13 | ||||
| -rw-r--r-- | drivers/net/e1000/e1000.h | 10 | ||||
| -rw-r--r-- | drivers/net/e1000/e1000_ethtool.c | 83 | ||||
| -rw-r--r-- | drivers/net/e1000/e1000_hw.c | 279 | ||||
| -rw-r--r-- | drivers/net/e1000/e1000_hw.h | 25 | ||||
| -rw-r--r-- | drivers/net/e1000/e1000_main.c | 187 | ||||
| -rw-r--r-- | drivers/net/e1000/e1000_osdep.h | 5 | ||||
| -rw-r--r-- | drivers/net/e1000/e1000_param.c | 66 | ||||
| -rw-r--r-- | drivers/net/eepro100.c | 35 |
20 files changed, 1033 insertions, 936 deletions
diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt index 298c4e1dce17..2ae26dee964d 100644 --- a/Documentation/networking/e1000.txt +++ b/Documentation/networking/e1000.txt @@ -1,7 +1,7 @@ Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters =============================================================== -April 23, 2002 +June 11, 2002 Contents @@ -95,8 +95,8 @@ For the latest Intel network drivers for Linux, go to: Command Line Parameters ======================= -If the driver is built as a module, the following parameters are used by -entering them on the command line with the modprobe or insmod command. +If the driver is built as a module, the following optional parameters are +used by entering them on the command line with the modprobe or insmod command. For example, with two PRO/1000 PCI adapters, entering: insmod e1000 TxDescriptors=80,128 @@ -141,7 +141,7 @@ Default Value: 80 RxIntDelay Valid Range: 0-65535 (0=off) -Default Value: 64 (82542, 82543, and 82544-based adapters) +Default Value: 0 (82542, 82543, and 82544-based adapters) 128 (82540, 82545, and 82546-based adapters) This value delays the generation of receive interrupts in units of 1.024 microseconds. Receive interrupt reduction can improve CPU efficiency if @@ -151,6 +151,14 @@ Default Value: 64 (82542, 82543, and 82544-based adapters) may be set too high, causing the driver to run out of available receive descriptors. + CAUTION: When setting RxIntDelay to a value other than 0, adapters based + on the Intel 82543 and 82544 LAN controllers may hang (stop + transmitting) under certain network conditions. If this occurs a + message is logged in the system event log. In addition, the + controller is automatically reset, restoring the network + connection. To eliminate the potential for the hang ensure that + RxIntDelay is set to 0. + Speed (adapters using copper connections only) Valid Settings: 0, 10, 100, 1000 Default Value: 0 (auto-negotiate at all supported speeds) @@ -229,16 +237,6 @@ Additional Configurations Known Issues ============ - Inconsistent Driver Behavior Under Heavy Traffic Loads - ------------------------------------------------------ - - Adapters based on the Intel 82543 and 82544 LAN controllers may hang (stop - transmitting) under certain network conditions. If this occurs a message - is logged in the system event log. In addition, the controller is - automatically reset, restoring the network connection. To eliminate the - potential for the hang change the RxIntDelay parameter to zero. For details - on the RxIntDelay parameter see the Command Line Parameters section. - Jumbo Frames System Requirement ------------------------------- diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 0070502b0c3d..3f7d7eb5df2a 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -21,13 +21,13 @@ Contributors: Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br> + PCI suspend/resume - Felipe Damasio <felipewd@terra.com.br> TODO, in rough priority order: * dev->tx_timeout * LinkChg interrupt * Support forcing media type with a module parameter, like dl2k.c/sundance.c - * Implement PCI suspend/resume * Constants (module parms?) for Rx work limit * support 64-bit PCI DMA * Complete reset on PciErr @@ -360,6 +360,7 @@ struct cp_private { unsigned int board_type; unsigned int wol_enabled : 1; /* Is Wake-on-LAN enabled? */ + u32 power_state[16]; struct mii_if_info mii_if; }; @@ -976,11 +977,11 @@ static void cp_reset_hw (struct cp_private *cp) static inline void cp_start_hw (struct cp_private *cp) { - cpw8(Cmd, RxOn | TxOn); if (cp->board_type == RTL8169) cpw16(CpCmd, PCIMulRW | RxChkSum); else cpw16(CpCmd, PCIMulRW | RxChkSum | CpRxOn | CpTxOn); + cpw8(Cmd, RxOn | TxOn); } static void cp_init_hw (struct cp_private *cp) @@ -1896,11 +1897,68 @@ static void __devexit cp_remove_one (struct pci_dev *pdev) kfree(dev); } +#ifdef CONFIG_PM +static int cp_suspend (struct pci_dev *pdev, u32 state) +{ + struct net_device *dev; + struct cp_private *cp; + unsigned long flags; + + dev = pci_get_drvdata (pdev); + cp = dev->priv; + + if (!dev || !netif_running (dev)) return 0; + + netif_device_detach (dev); + netif_stop_queue (dev); + + spin_lock_irqsave (&cp->lock, flags); + + /* Disable Rx and Tx */ + cpw16 (IntrMask, 0); + cpw8 (Cmd, cpr8 (Cmd) & (~RxOn | ~TxOn)); + + spin_unlock_irqrestore (&cp->lock, flags); + + if (cp->pdev && cp->wol_enabled) { + pci_save_state (cp->pdev, cp->power_state); + cp_set_d3_state (cp); + } + + return 0; +} + +static int cp_resume (struct pci_dev *pdev) +{ + struct net_device *dev; + struct cp_private *cp; + + dev = pci_get_drvdata (pdev); + cp = dev->priv; + + netif_device_attach (dev); + + if (cp->pdev && cp->wol_enabled) { + pci_set_power_state (cp->pdev, 0); + pci_restore_state (cp->pdev, cp->power_state); + } + + cp_init_hw (cp); + netif_start_queue (dev); + + return 0; +} +#endif /* CONFIG_PM */ + static struct pci_driver cp_driver = { .name = DRV_NAME, .id_table = cp_pci_tbl, .probe = cp_init_one, .remove = __devexit_p(cp_remove_one), +#ifdef CONFIG_PM + .resume = cp_resume, + .suspend = cp_suspend, +#endif }; static int __init cp_init (void) diff --git a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h index 9e6b5d3d4e26..ed0dca565759 100644 --- a/drivers/net/e100/e100.h +++ b/drivers/net/e100/e100.h @@ -91,13 +91,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <linux/version.h> #include <linux/string.h> #include <linux/wait.h> +#include <linux/reboot.h> #include <asm/io.h> #include <asm/unaligned.h> #include <asm/processor.h> -#ifdef SIOCETHTOOL #include <linux/ethtool.h> #include <linux/inetdevice.h> -#endif #include <linux/if.h> #include <asm/uaccess.h> @@ -147,6 +146,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define E100_MAX_SCB_WAIT 100 /* Max udelays in wait_scb */ #define E100_MAX_CU_IDLE_WAIT 50 /* Max udelays in wait_cus_idle */ +/* HWI feature related constant */ +#define HWI_MAX_LOOP 100 +#define MAX_SAME_RESULTS 3 +#define HWI_REGISTER_GRANULARITY 80 /* register granularity = 80 Cm */ +#define HWI_NEAR_END_BOUNDARY 1000 /* Near end is defined as < 10 meters */ + /* CPUSAVER_BUNDLE_MAX: 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 @@ -504,6 +509,7 @@ enum led_state_e { #define IS_ICH 0x00000020 #define DF_SPEED_FORCED 0x00000040 /* set if speed is forced */ #define LED_IS_ON 0x00000080 /* LED is turned ON by the driver */ +#define DF_LINK_FC_TX_ONLY 0x00000100 /* Received PAUSE frames are honored*/ typedef struct net_device_stats net_dev_stats_t; @@ -774,15 +780,7 @@ typedef struct _tcb_ipcb_t { u16 total_tcp_payload; } tcb_ipcb_t __attribute__ ((__packed__)); -#ifdef MAX_SKB_FRAGS -#define E100_ZEROCOPY -#endif - -#ifdef E100_ZEROCOPY #define E100_TBD_ARRAY_SIZE (2+MAX_SKB_FRAGS) -#else -#define E100_TBD_ARRAY_SIZE 2 -#endif /*E100_ZEROCOPY */ /* Transmit Command Block (TCB)*/ struct _tcb_t { @@ -803,19 +801,15 @@ struct _tcb_t { */ tbd_t *tbd_ptr; -#ifdef E100_ZEROCOPY u32 tcb_tbd_dflt_ptr; /* TBD address for non-segmented packet */ u32 tcb_tbd_expand_ptr; /* TBD address for segmented packet */ -#endif /*E100_ZEROCOPY */ struct sk_buff *tcb_skb; /* the associated socket buffer */ dma_addr_t tcb_phys; /* phys addr of the TCB */ } __attribute__ ((__packed__)); -#ifndef _TCB_T_ #define _TCB_T_ typedef struct _tcb_t tcb_t; -#endif /* Receive Frame Descriptor (RFD) - will be using the simple model*/ struct _rfd_t { @@ -836,10 +830,8 @@ struct _rfd_t { } __attribute__ ((__packed__)); -#ifndef _RFD_T_ #define _RFD_T_ typedef struct _rfd_t rfd_t; -#endif /* Receive Buffer Descriptor (RBD)*/ typedef struct _rbd_t { @@ -901,14 +893,12 @@ struct cfg_params { int PollingMaxWork; u32 b_params; }; -#ifdef ETHTOOL_TEST struct ethtool_lpbk_data{ dma_addr_t dma_handle; tcb_t *tcb; rfd_t *rfd; }; -#endif struct e100_private { u32 flags; /* board management flags */ @@ -987,28 +977,33 @@ struct e100_private { rwlock_t isolate_lock; int driver_isolated; + char *id_string; + char *cable_status; + char *mdix_status; + + /* Variables for HWI */ + int saved_open_circut; + int saved_short_circut; + int saved_distance; + int saved_i; + int saved_same; + unsigned char hwi_started; + struct timer_list hwi_timer; /* hwi timer id */ u32 speed_duplex_caps; /* adapter's speed/duplex capabilities */ struct tasklet_struct polling_tasklet; -#ifdef ETHTOOL_GWOL /* WOL params for ethtool */ u32 wolsupported; u32 wolopts; u16 ip_lbytes; -#endif -#ifdef ETHTOOL_TEST struct ethtool_lpbk_data loopback; -#endif -#ifdef ETHTOOL_PHYS_ID struct timer_list blink_timer; /* led blink timer id */ -#endif #ifdef CONFIG_PM u32 pci_state[16]; #endif - }; #define E100_AUTONEG 0 @@ -1036,8 +1031,6 @@ extern void e100_deisolate_driver(struct e100_private *bdp, extern unsigned char e100_hw_reset_recover(struct e100_private *bdp, u32 reset_cmd); -#ifdef ETHTOOL_TEST - #define ROM_TEST_FAIL 0x01 #define REGISTER_TEST_FAIL 0x02 #define SELF_TEST_FAIL 0x04 @@ -1053,6 +1046,5 @@ enum test_offsets { E100_LPBK_PHY_FAIL, E100_MAX_TEST_RES }; -#endif #endif diff --git a/drivers/net/e100/e100_config.c b/drivers/net/e100/e100_config.c index cce55296ebb1..d90ab621f93b 100644 --- a/drivers/net/e100/e100_config.c +++ b/drivers/net/e100/e100_config.c @@ -86,10 +86,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * operating system. * * * **********************************************************************/ -#ifdef SIOCETHTOOL -#include <linux/ethtool.h> -#endif - #include "e100_config.h" static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable); @@ -308,85 +304,58 @@ exit: /** * e100_config_fc - config flow-control state - * @bdp: atapter's private data struct + * @bdp: adapter's private data struct * * This routine will enable or disable flow control support in the adapter's * config block. Flow control will be enable only if requested using the command * line option, and if the link is flow-contorl capable (both us and the link - * partner). - * - * Returns: - * true: if then option was indeed changed - * false: if no change was needed + * partner). But, if link partner is capable of autoneg, but not capable of + * flow control, received PAUSE frames are still honored. */ -unsigned char +void e100_config_fc(struct e100_private *bdp) { unsigned char enable = false; - unsigned char changed = false; - /* 82557 doesn't support fc. Don't touch this option */ if (!(bdp->flags & IS_BACHELOR)) - return false; + return; /* Enable fc if requested and if the link supports it */ - if ((bdp->params.b_params & PRM_FC) && (bdp->flags & DF_LINK_FC_CAP)) { + if ((bdp->params.b_params & PRM_FC) && (bdp->flags & + (DF_LINK_FC_CAP | DF_LINK_FC_TX_ONLY))) { enable = true; } spin_lock_bh(&(bdp->config_lock)); if (enable) { - - if (bdp->config[16] != DFLT_FC_DELAY_LSB) { + if (bdp->flags & DF_LINK_FC_TX_ONLY) { + /* If link partner is capable of autoneg, but */ + /* not capable of flow control, Received PAUSE */ + /* frames are still honored, i.e., */ + /* transmitted frames would be paused by */ + /* incoming PAUSE frames */ + bdp->config[16] = DFLT_NO_FC_DELAY_LSB; + bdp->config[17] = DFLT_NO_FC_DELAY_MSB; + bdp->config[19] &= ~(CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART); + bdp->config[19] |= CB_CFIG_FC_REJECT; + bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; + } else { bdp->config[16] = DFLT_FC_DELAY_LSB; - E100_CONFIG(bdp, 16); - changed = true; - } - - if (bdp->config[17] != DFLT_FC_DELAY_LSB) { bdp->config[17] = DFLT_FC_DELAY_MSB; - E100_CONFIG(bdp, 17); - changed = true; - } - - /* check if *all* fc config options were already set */ - if (((bdp->config[19] & CB_CFIG_FC_OPTS) != CB_CFIG_FC_OPTS) || - (bdp->config[19] & CB_CFIG_TX_FC_DIS)) { - bdp->config[19] |= CB_CFIG_FC_OPTS; bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; - E100_CONFIG(bdp, 19); - changed = true; } - } else { - if (bdp->config[16] != DFLT_NO_FC_DELAY_LSB) { - bdp->config[16] = DFLT_NO_FC_DELAY_LSB; - E100_CONFIG(bdp, 16); - changed = true; - } - - if (bdp->config[17] != DFLT_NO_FC_DELAY_MSB) { - bdp->config[17] = DFLT_NO_FC_DELAY_MSB; - E100_CONFIG(bdp, 17); - changed = true; - } - - /* check if *any* fc config options was already set */ - if ((bdp->config[19] & CB_CFIG_FC_OPTS) || - !(bdp->config[19] & CB_CFIG_TX_FC_DIS)) { - - bdp->config[19] &= ~CB_CFIG_FC_OPTS; - bdp->config[19] |= CB_CFIG_TX_FC_DIS; - E100_CONFIG(bdp, 19); - changed = true; - } + bdp->config[16] = DFLT_NO_FC_DELAY_LSB; + bdp->config[17] = DFLT_NO_FC_DELAY_MSB; + bdp->config[19] &= ~CB_CFIG_FC_OPTS; + bdp->config[19] |= CB_CFIG_TX_FC_DIS; } - + E100_CONFIG(bdp, 19); spin_unlock_bh(&(bdp->config_lock)); - return changed; + return; } /** @@ -566,7 +535,6 @@ e100_config_long_rx(struct e100_private *bdp, unsigned char enable) } } -#ifdef ETHTOOL_GWOL /** * e100_config_wol * @bdp: atapter's private data struct @@ -591,7 +559,6 @@ e100_config_wol(struct e100_private *bdp) spin_unlock_bh(&(bdp->config_lock)); } -#endif /** * e100_config_loopback_mode @@ -618,7 +585,7 @@ e100_config_loopback_mode(struct e100_private *bdp, u8 mode) config_byte = CB_CFIG_LOOPBACK_EXTERNAL; break; default: - printk(KERN_NOTICE "e100_config_loopback_mode: " + printk(KERN_NOTICE "e100: e100_config_loopback_mode: " "Invalid argument 'mode': %d\n", mode); goto exit; } diff --git a/drivers/net/e100/e100_config.h b/drivers/net/e100/e100_config.h index 6172ce27ef4b..e114a6cc9917 100644 --- a/drivers/net/e100/e100_config.h +++ b/drivers/net/e100/e100_config.h @@ -198,7 +198,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. extern void e100_config_init(struct e100_private *bdp); extern unsigned char e100_force_config(struct e100_private *bdp); extern unsigned char e100_config(struct e100_private *bdp); -extern unsigned char e100_config_fc(struct e100_private *bdp); +extern void e100_config_fc(struct e100_private *bdp); extern void e100_config_promisc(struct e100_private *bdp, unsigned char enable); extern void e100_config_brdcast_dsbl(struct e100_private *bdp); extern void e100_config_mulcast_enbl(struct e100_private *bdp, diff --git a/drivers/net/e100/e100_eeprom.c b/drivers/net/e100/e100_eeprom.c index 5062699b9d24..58eeeac32d9d 100644 --- a/drivers/net/e100/e100_eeprom.c +++ b/drivers/net/e100/e100_eeprom.c @@ -145,8 +145,6 @@ eeprom_set_semaphore(struct e100_private *adapter) data |= SCB_GCR2_EEPROM_ACCESS_SEMAPHORE; writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter)); - barrier(); - // Check to see if this bit set or not. data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); @@ -224,6 +222,7 @@ e100_eeprom_size(struct e100_private *adapter) x &= ~EEDI; // address consists of all zeros writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); + readw(&(adapter->scb->scb_status)); udelay(EEPROM_STALL_TIME); raise_clock(adapter, &x); lower_clock(adapter, &x); diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index d58486f305bf..8746842f0952 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -93,8 +93,30 @@ Portions (C) 2002 Red Hat, Inc. under the terms of the GNU GPL v2. * * **********************************************************************/ -#undef __NO_VERSION__ - +/* Change Log + * + * 2.1.6 7/5/02 + * o Added device ID support for Dell LOM. + * o Added device ID support for 82511QM mobile nics. + * o Bug fix: ethtool get/set EEPROM routines modified to use byte + * addressing rather than word addressing. + * o Feature: added MDIX mode support for 82550 and up. + * o Bug fix: added reboot notifer to setup WOL settings when + * shutting system down. + * o Cleanup: removed yield() redefinition (Andrew Morton, + * akpm@zip.com.au). + * o Bug fix: flow control now working when link partner is + * autoneg capable but not flow control capable. + * o Bug fix: added check for corrupted EEPROM + * o Bug fix: don't report checksum offloading for the older + * controllers that don't support the feature. + * o Bug fix: calculate cable diagnostics when link goes down + * rather than when queuering /proc file. + * o Cleanup: move mdi_access_lock to local get/set mdi routines. + * + * 2.0.30 5/30/02 + */ + #include <linux/config.h> #include <net/checksum.h> #include <linux/tcp.h> @@ -105,11 +127,7 @@ Portions (C) 2002 Red Hat, Inc. under the terms of the GNU GPL v2. #include "e100_phy.h" #include "e100_vendor.h" -#ifndef CONFIG_PROC_FS -#undef E100_CONFIG_PROC_FS -#endif - -#ifdef E100_CONFIG_PROC_FS +#ifdef CONFIG_PROC_FS extern int e100_create_proc_subdir(struct e100_private *); extern void e100_remove_proc_subdir(struct e100_private *); #else @@ -117,41 +135,24 @@ extern void e100_remove_proc_subdir(struct e100_private *); #define e100_remove_proc_subdir(X) do {} while(0) #endif -#ifdef SIOCETHTOOL -#define E100_ETHTOOL_IOCTL -#endif -#ifdef E100_ETHTOOL_IOCTL static int e100_do_ethtool_ioctl(struct net_device *, struct ifreq *); static void e100_get_speed_duplex_caps(struct e100_private *); static int e100_ethtool_get_settings(struct net_device *, struct ifreq *); static int e100_ethtool_set_settings(struct net_device *, struct ifreq *); -#ifdef ETHTOOL_GDRVINFO static int e100_ethtool_get_drvinfo(struct net_device *, struct ifreq *); -#endif -#ifdef ETHTOOL_GEEPROM static int e100_ethtool_eeprom(struct net_device *, struct ifreq *); #define E100_EEPROM_MAGIC 0x1234 -#endif -#ifdef ETHTOOL_GLINK static int e100_ethtool_glink(struct net_device *, struct ifreq *); -#endif -#ifdef ETHTOOL_NWAY_RST static int e100_ethtool_nway_rst(struct net_device *, struct ifreq *); -#endif -#ifdef ETHTOOL_GWOL static int e100_ethtool_wol(struct net_device *, struct ifreq *); static unsigned char e100_setup_filter(struct e100_private *bdp); static void e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp); static u16 e100_get_ip_lbytes(struct net_device *dev); extern void e100_config_wol(struct e100_private *bdp); -#endif -#ifdef ETHTOOL_TEST extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags); static int e100_ethtool_test(struct net_device *, struct ifreq *); -#endif -#ifdef ETHTOOL_GSTRINGS static int e100_ethtool_gstrings(struct net_device *, struct ifreq *); static char *test_strings[] = { "E100_EEPROM_TEST_FAIL", @@ -163,19 +164,10 @@ static char *test_strings[] = { "E100_LPBK_PHY_FAIL" }; -#endif -#ifdef ETHTOOL_PHYS_ID static int e100_ethtool_led_blink(struct net_device *, struct ifreq *); -#endif -#endif /*E100_ETHTOOL_IOCTL */ -#ifdef SIOCGMIIPHY -#define E100_MII_IOCTL -#endif -#ifdef E100_MII_IOCTL #include <linux/mii.h> static int e100_mii_ioctl(struct net_device *, struct ifreq *, int); -#endif /*E100_MII_IOCTL */ static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *, nxmit_cb_entry_t *); @@ -184,23 +176,24 @@ static void e100_non_tx_background(unsigned long); /* Global Data structures and variables */ char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation"; - -#define E100_VERSION "2.0.30-k1" - -#define E100_FULL_DRIVER_NAME "Intel(R) PRO/100 Fast Ethernet Adapter - Loadable driver, ver " - -const char *e100_version = E100_VERSION; -const char *e100_full_driver_name = E100_FULL_DRIVER_NAME E100_VERSION; -char *e100_short_driver_name = "e100"; +char e100_driver_version[]="2.1.6-k1"; +const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver"; +char e100_short_driver_name[] = "e100"; static int e100nics = 0; #ifdef CONFIG_PM -static int e100_save_state(struct pci_dev *pcid, u32 state); +static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); static int e100_suspend(struct pci_dev *pcid, u32 state); -static int e100_enable_wake(struct pci_dev *pcid, u32 state, int enable); static int e100_resume(struct pci_dev *pcid); +struct notifier_block e100_notifier = { + notifier_call: e100_notify_reboot, + next: NULL, + priority: 0 +}; #endif +static void e100_get_mdix_status(struct e100_private *bdp); + /*********************************************************************/ /*! This is a GCC extension to ANSI C. * See the item "Labeled Elements in Initializers" in the section @@ -250,6 +243,7 @@ static void e100_rd_pwa_no(struct e100_private *); extern u16 e100_eeprom_read(struct e100_private *, u16); extern void e100_eeprom_write_block(struct e100_private *, u16, u16 *, u16); extern u16 e100_eeprom_size(struct e100_private *); +u16 e100_eeprom_calculate_chksum(struct e100_private *adapter); static unsigned char e100_clr_cntrs(struct e100_private *); static unsigned char e100_load_microcode(struct e100_private *); @@ -391,6 +385,8 @@ u32 e100_rx_srv(struct e100_private *, u32, int *); void e100_polling_tasklet(unsigned long); void e100_watchdog(struct net_device *); +static void e100_do_hwi(struct net_device *); +static void e100_hwi_restore(struct e100_private *); void e100_refresh_txthld(struct e100_private *); void e100_manage_adaptive_ifs(struct e100_private *); void e100_clear_pools(struct e100_private *); @@ -400,7 +396,7 @@ static inline tcb_t *e100_prepare_xmit_buff(struct e100_private *, static void e100_set_multi_exec(struct net_device *dev); MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); -MODULE_DESCRIPTION(E100_FULL_DRIVER_NAME E100_VERSION); +MODULE_DESCRIPTION("Intel(R) PRO/100 Network Driver"); MODULE_LICENSE("Dual BSD/GPL"); E100_PARAM(TxDescriptors, "Number of transmit descriptors"); @@ -429,7 +425,7 @@ static inline void e100_exec_cmd(struct e100_private *bdp, u8 cmd_low) { writeb(cmd_low, &(bdp->scb->scb_cmd_low)); - readw(&(bdp->scb->scb_status)); /* flashes last write, read-safe */ + readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ } /** @@ -484,7 +480,7 @@ inline unsigned char e100_wait_exec_simple(struct e100_private *bdp, u8 scb_cmd_low) { if (!e100_wait_scb(bdp)) { - printk(KERN_DEBUG "%s e100_wait_exec_simple: Wait failed\n", + printk(KERN_DEBUG "e100: %s: e100_wait_exec_simple: failed\n", bdp->device->name); return false; } @@ -496,7 +492,7 @@ void e100_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd) { writel(phys_addr, &(bdp->scb->scb_gen_ptr)); - readw(&(bdp->scb->scb_status)); /* flashes last write, read-safe */ + readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ e100_exec_cmd(bdp, cmd); } @@ -580,10 +576,11 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) struct net_device *dev = NULL; struct e100_private *bdp = NULL; int rc = 0; + u16 cal_checksum, read_checksum; dev = alloc_etherdev(sizeof (struct e100_private)); if (dev == NULL) { - printk(KERN_ERR "Not able to alloc etherdev struct\n"); + printk(KERN_ERR "e100: Not able to alloc etherdev struct\n"); rc = -ENODEV; goto out; } @@ -592,7 +589,8 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) if (first_time) { first_time = false; - printk(KERN_NOTICE "%s\n", e100_full_driver_name); + printk(KERN_NOTICE "%s - version %s\n", + e100_full_driver_name, e100_driver_version); printk(KERN_NOTICE "%s\n", e100_copyright); printk(KERN_NOTICE "\n"); } @@ -622,6 +620,10 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) bdp->watchdog_timer.data = (unsigned long) dev; bdp->watchdog_timer.function = (void *) &e100_watchdog; + init_timer(&bdp->hwi_timer); + bdp->hwi_timer.data = (unsigned long) dev; + bdp->hwi_timer.function = (void *) &e100_do_hwi; + if ((rc = e100_pci_setup(pcid, bdp)) != 0) { goto err_dealloc; } @@ -647,16 +649,25 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) } else { bdp->rfd_size = 16; } - e100_check_options(e100nics, bdp); if (!e100_init(bdp)) { - printk(KERN_ERR "Failed to initialize e100, instance #%d\n", + printk(KERN_ERR "e100: Failed to initialize, instance #%d\n", e100nics); rc = -ENODEV; goto err_pci; } + /* Check if checksum is valid */ + cal_checksum = e100_eeprom_calculate_chksum(bdp); + read_checksum = e100_eeprom_read(bdp, (bdp->eeprom_size - 1)); + if (cal_checksum != read_checksum) { + printk(KERN_ERR "e100: Corrupted EERPROM on instance #%d\n", + e100nics); + rc = -ENODEV; + goto err_pci; + } + dev->irq = pcid->irq; dev->open = &e100_open; dev->hard_start_xmit = &e100_xmit_frame; @@ -666,16 +677,12 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) dev->set_multicast_list = &e100_set_multi; dev->set_mac_address = &e100_set_mac; dev->do_ioctl = &e100_ioctl; -#ifdef E100_ZEROCOPY if (bdp->flags & USE_IPCB) { dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; } -#endif e100nics++; -#ifdef E100_ETHTOOL_IOCTL e100_get_speed_duplex_caps(bdp); -#endif /*E100_ETHTOOL_IOCTL */ if ((rc = register_netdev(dev)) != 0) { goto err_pci; @@ -683,15 +690,26 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) bdp->device_type = ent->driver_data; printk(KERN_NOTICE - "%s: %s\n", bdp->device->name, e100_get_brand_msg(bdp)); + "e100: %s: %s\n", + bdp->device->name, e100_get_brand_msg(bdp)); e100_print_brd_conf(bdp); + bdp->id_string = e100_get_brand_msg(bdp); + e100_get_mdix_status(bdp); + + if (netif_carrier_ok(bdp->device)) + bdp->cable_status = "Cable OK"; + else { + if (bdp->rev_id < D102_REV_ID) + bdp->cable_status = "Not supported"; + else + bdp->cable_status = "Not available"; + } if (e100_create_proc_subdir(bdp) < 0) { - printk(KERN_ERR "Failed to create proc directory for %s\n", + printk(KERN_ERR "e100: Failed to create proc dir for %s\n", bdp->device->name); } -#ifdef ETHTOOL_GWOL /* Disabling all WOLs as initialization */ bdp->wolsupported = bdp->wolopts = 0; if (bdp->rev_id >= D101A4_REV_ID) { @@ -700,7 +718,6 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) bdp->wolsupported |= WAKE_UCAST | WAKE_ARP; bdp->wolopts = WAKE_MAGIC; } -#endif printk(KERN_NOTICE "\n"); @@ -762,7 +779,6 @@ e100_remove1(struct pci_dev *pcid) bdp->non_tx_command_state = E100_NON_TX_IDLE; } -#ifdef ETHTOOL_GWOL /* Set up wol options and enable PME if wol is enabled */ if (bdp->wolopts) { e100_do_wol(pcid, bdp); @@ -772,7 +788,6 @@ e100_remove1(struct pci_dev *pcid) /* If system powers down, device is switched from D1 to D3 */ pci_set_power_state(pcid, 1); } -#endif e100_clear_structs(dev); @@ -786,27 +801,33 @@ static struct pci_driver e100_driver = { id_table: e100_id_table, probe: e100_found1, remove: __devexit_p(e100_remove1), -#ifdef CONFIG_PM +#ifdef CONFIG_PM suspend: e100_suspend, resume: e100_resume, - save_state: e100_save_state, - enable_wake: e100_enable_wake, -#else - suspend: NULL, - resume: NULL, #endif }; static int __init e100_init_module(void) { - return pci_module_init(&e100_driver); + int ret; + ret = pci_module_init(&e100_driver); + +#ifdef CONFIG_PM + if(ret >= 0) + register_reboot_notifier(&e100_notifier); +#endif + return ret; } static void __exit e100_cleanup_module(void) { +#ifdef CONFIG_PM + unregister_reboot_notifier(&e100_notifier); +#endif + pci_unregister_driver(&e100_driver); } @@ -824,9 +845,10 @@ void __devinit e100_check_options(int board, struct e100_private *bdp) { if (board >= E100_MAX_NIC) { - printk(KERN_NOTICE "No configuration available for board #%d\n", + printk(KERN_NOTICE + "e100: No configuration available for board #%d\n", board); - printk(KERN_NOTICE "Using defaults for all values\n"); + printk(KERN_NOTICE "e100: Using defaults for all values\n"); board = E100_MAX_NIC; } @@ -907,13 +929,14 @@ e100_set_int_option(int *option, int val, int min, int max, int default_val, } else if ((val < min) || (val > max)) { printk(KERN_NOTICE - "Invalid %s specified (%i). Valid range is %i-%i\n", + "e100: Invalid %s specified (%i). " + "Valid range is %i-%i\n", name, val, min, max); - printk(KERN_NOTICE "Using default %s of %i\n", name, + printk(KERN_NOTICE "e100: Using default %s of %i\n", name, default_val); *option = default_val; } else { - printk(KERN_INFO "Using specified %s of %i\n", name, val); + printk(KERN_INFO "e100: Using specified %s of %i\n", name, val); *option = val; } } @@ -941,15 +964,16 @@ e100_set_bool_option(struct e100_private *bdp, int val, u32 mask, } else if ((val != true) && (val != false)) { printk(KERN_NOTICE - "Invalid %s specified (%i). Valid values are %i/%i\n", + "e100: Invalid %s specified (%i). " + "Valid values are %i/%i\n", name, val, false, true); - printk(KERN_NOTICE "Using default %s of %i\n", name, + printk(KERN_NOTICE "e100: Using default %s of %i\n", name, default_val); if (default_val) bdp->params.b_params |= mask; } else { - printk(KERN_INFO "Using specified %s of %i\n", name, val); + printk(KERN_INFO "e100: Using specified %s of %i\n", name, val); if (val) bdp->params.b_params |= mask; } @@ -1035,9 +1059,7 @@ e100_close(struct net_device *dev) bdp->intr_mask = SCB_INT_MASK; e100_isolate_driver(bdp); -#ifdef ETHTOOL_GWOL bdp->ip_lbytes = e100_get_ip_lbytes(dev); -#endif free_irq(dev->irq, dev); e100_clear_pools(bdp); @@ -1198,7 +1220,8 @@ e100_set_multi_exec(struct net_device *dev) } if (!e100_exec_non_cu_cmd(bdp, cmd)) { - printk(KERN_WARNING "%s: Multicast setup failed\n", dev->name); + printk(KERN_WARNING "e100: %s: Multicast setup failed\n", + dev->name); } } @@ -1247,19 +1270,15 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) switch (cmd) { -#ifdef E100_ETHTOOL_IOCTL case SIOCETHTOOL: return e100_do_ethtool_ioctl(dev, ifr); break; -#endif /*E100_ETHTOOL_IOCTL */ -#ifdef E100_MII_IOCTL case SIOCGMIIPHY: /* Get address of MII PHY in use. */ case SIOCGMIIREG: /* Read MII PHY register. */ case SIOCSMIIREG: /* Write to MII PHY register. */ return e100_mii_ioctl(dev, ifr, cmd); break; -#endif /*E100_MII_IOCTL */ default: return -EOPNOTSUPP; @@ -1286,7 +1305,7 @@ e100_init(struct e100_private *bdp) e100_sw_init(bdp); if (!e100_selftest(bdp, NULL, NULL)) { - printk(KERN_ERR "selftest failed\n"); + printk(KERN_ERR "e100: selftest failed\n"); return false; } @@ -1296,7 +1315,7 @@ e100_init(struct e100_private *bdp) e100_rd_pwa_no(bdp); if (!e100_hw_init(bdp, PORT_SOFTWARE_RESET)) { - printk(KERN_ERR "hw init failed\n"); + printk(KERN_ERR "e100: hw init failed\n"); return false; } e100_dis_intr(bdp); @@ -1462,7 +1481,6 @@ e100_setup_tcb_pool(tcb_t *head, unsigned int qlen, struct e100_private *bdp) cpu_to_le32(pcurr_tcb->tcb_phys + 0x10); } -#ifdef E100_ZEROCOPY if (bdp->flags & IS_BACHELOR) { pcurr_tcb->tcb_tbd_expand_ptr = cpu_to_le32(pcurr_tcb->tcb_phys + 0x20); @@ -1471,7 +1489,6 @@ e100_setup_tcb_pool(tcb_t *head, unsigned int qlen, struct e100_private *bdp) cpu_to_le32(pcurr_tcb->tcb_phys + 0x10); } pcurr_tcb->tcb_tbd_dflt_ptr = pcurr_tcb->tcb_tbd_ptr; -#endif if (bdp->flags & USE_IPCB) { pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[1]); @@ -1532,7 +1549,7 @@ e100_alloc_space(struct e100_private *bdp) err: printk(KERN_ERR - "%s - Failed to allocate memory\n", e100_short_driver_name); + "e100: Failed to allocate memory\n"); return -ENOMEM; } @@ -1665,7 +1682,7 @@ e100_watchdog(struct net_device *dev) if (!netif_running(dev)) { goto exit; } - spin_lock_bh(&(bdp->mdi_access_lock)); + e100_get_mdix_status(bdp); /* check if link state has changed */ if (e100_phy_check(bdp)) { @@ -1677,11 +1694,38 @@ e100_watchdog(struct net_device *dev) "Half" : "Full"); e100_config_fc(bdp); - e100_config(bdp); + e100_config(bdp); + bdp->cable_status = "Cable OK"; } else { printk(KERN_ERR "e100: %s NIC Link is Down\n", bdp->device->name); + if (bdp->rev_id < D102_REV_ID) + bdp->cable_status = "Not supported"; + else { + /* Initiate hwi, ie, cable diagnostic */ + bdp->saved_open_circut = 0xffff; + bdp->saved_short_circut = 0xffff; + bdp->saved_distance = 0xffff; + bdp->saved_i = 0; + bdp->saved_same = 0; + bdp->hwi_started = 1; + + /* Disable MDI/MDI-X auto switching */ + e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, + MDI_MDIX_RESET_ALL_MASK); + + /* Set to 100 Full as required by hwi test */ + e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, + BMCR_SPEED100 | BMCR_FULLDPLX); + + /* Enable and execute HWI test */ + e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr, + (HWI_TEST_ENABLE | HWI_TEST_EXECUTE)); + + /* Launch hwi timer in 1 msec */ + mod_timer(&(bdp->hwi_timer), jiffies + (HZ / 1000) ); + } } } @@ -1722,8 +1766,6 @@ e100_watchdog(struct net_device *dev) wmb(); - spin_unlock_bh(&(bdp->mdi_access_lock)); - /* relaunch watchdog timer in 2 sec */ mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ)); @@ -1869,6 +1911,7 @@ e100intr(int irq, void *dev_inst, struct pt_regs *regs) e100_dis_intr(bdp); writew(intr_status, &bdp->scb->scb_status); /* ack intrs */ + readw(&bdp->scb->scb_status); /* the device is closed, don't continue or else bad things may happen. */ if (!netif_running(dev)) { @@ -1923,7 +1966,6 @@ static void inline e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb) { if (tcb->tcb_skb) { -#ifdef E100_ZEROCOPY int i; tbd_t *tbd_arr = tcb->tbd_ptr; int frags = skb_shinfo(tcb->tcb_skb)->nr_frags; @@ -1934,11 +1976,6 @@ e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb) le16_to_cpu(tbd_arr->tbd_buf_cnt), PCI_DMA_TODEVICE); } -#else - pci_unmap_single(bdp->pdev, - le32_to_cpu((tcb->tbd_ptr)->tbd_buf_addr), - tcb->tcb_skb->len, PCI_DMA_TODEVICE); -#endif dev_kfree_skb_irq(tcb->tcb_skb); tcb->tcb_skb = NULL; } @@ -2181,7 +2218,6 @@ e100_refresh_txthld(struct e100_private *bdp) } /* end underrun check */ } -#ifdef E100_ZEROCOPY /** * e100_pseudo_hdr_csum - compute IP pseudo-header checksum * @ip: points to the header of the IP packet @@ -2207,7 +2243,6 @@ e100_pseudo_hdr_csum(const struct iphdr *ip) return FOLD_CSUM(pseudo); } -#endif /* E100_ZEROCOPY */ /** * e100_prepare_xmit_buff - prepare a buffer for transmission @@ -2247,7 +2282,6 @@ e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) tcb->tcb_skb = skb; -#ifdef E100_ZEROCOPY if (skb->ip_summed == CHECKSUM_HW) { const struct iphdr *ip = skb->nh.iph; @@ -2312,12 +2346,6 @@ e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1; tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr; } -#else - (tcb->tbd_ptr)->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE)); - (tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len); -#endif /* clear the S-BIT on the previous tcb */ prev_tcb = bdp->tcb_pool.data; @@ -2377,12 +2405,12 @@ e100_start_cu(struct e100_private *bdp, tcb_t *tcb) // The last command was a non_tx CU command if (!e100_wait_cus_idle(bdp)) printk(KERN_DEBUG - "%s cu_start: timeout waiting for cu\n", + "e100: %s: cu_start: timeout waiting for cu\n", bdp->device->name); if (!e100_wait_exec_cmplx(bdp, (u32) (tcb->tcb_phys), SCB_CUC_START)) { printk(KERN_DEBUG - "%s cu_start: timeout waiting for scb\n", + "e100: %s: cu_start: timeout waiting for scb\n", bdp->device->name); e100_exec_cmplx(bdp, (u32) (tcb->tcb_phys), SCB_CUC_START); @@ -2498,7 +2526,8 @@ e100_setup_iaaddr(struct e100_private *bdp, u8 *eaddr) res = e100_exec_non_cu_cmd(bdp, cmd); if (!res) - printk(KERN_WARNING "%s IA setup failed\n", bdp->device->name); + printk(KERN_WARNING "e100: %s: IA setup failed\n", + bdp->device->name); exit: return res; @@ -2544,7 +2573,8 @@ e100_start_ru(struct e100_private *bdp) if (!e100_wait_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START)) { printk(KERN_DEBUG - "%s start_ru: wait_scb failed\n", bdp->device->name); + "e100: %s: start_ru: wait_scb failed\n", + bdp->device->name); e100_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START); } if (bdp->next_cu_cmd == RESUME_NO_WAIT) { @@ -3051,8 +3081,10 @@ e100_print_brd_conf(struct e100_private *bdp) /* Print the string if checksum Offloading was enabled */ if (bdp->flags & DF_CSUM_OFFLOAD) printk(KERN_NOTICE " Hardware receive checksums enabled\n"); - else - printk(KERN_NOTICE " Hardware receive checksums disabled\n"); + else { + if (bdp->rev_id >= D101MA_REV_ID) + printk(KERN_NOTICE " Hardware receive checksums disabled\n"); + } if ((bdp->flags & DF_UCODE_LOADED)) printk(KERN_NOTICE " cpu cycle saver enabled\n"); @@ -3125,9 +3157,8 @@ e100_pci_setup(struct pci_dev *pcid, struct e100_private *bdp) bdp->scb = (scb_t *) ioremap_nocache(dev->mem_start, sizeof (scb_t)); if (!bdp->scb) { - printk(KERN_ERR "%s - %s: Failed to map PCI address 0x%lX\n", - e100_short_driver_name, dev->name, - pci_resource_start(pcid, 0)); + printk(KERN_ERR "e100: %s: Failed to map PCI address 0x%lX\n", + dev->name, pci_resource_start(pcid, 0)); rc = -ENOMEM; goto err_region; } @@ -3151,6 +3182,13 @@ e100_isolate_driver(struct e100_private *bdp) del_timer_sync(&bdp->watchdog_timer); + del_timer_sync(&bdp->hwi_timer); + /* If in middle of cable diag, */ + if (bdp->hwi_started) { + bdp->hwi_started = 0; + e100_hwi_restore(bdp); + } + if (netif_running(bdp->device)) netif_stop_queue(bdp->device); @@ -3218,7 +3256,8 @@ e100_hw_reset_recover(struct e100_private *bdp, u32 reset_cmd) if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr)) { printk(KERN_ERR - "e100_hw_reset_recover: setup iaaddr failed\n"); + "e100: e100_hw_reset_recover: " + "setup iaaddr failed\n"); return false; } @@ -3248,7 +3287,7 @@ e100_deisolate_driver(struct e100_private *bdp, u8 recover, u8 full_init) if (full_init) { e100_sw_reset(bdp, PORT_SOFTWARE_RESET); if (!e100_hw_reset_recover(bdp, PORT_SOFTWARE_RESET)) - printk(KERN_ERR "e100_deisolate_driver:" + printk(KERN_ERR "e100: e100_deisolate_driver:" " HW SOFTWARE reset recover failed\n"); } @@ -3262,7 +3301,7 @@ e100_deisolate_driver(struct e100_private *bdp, u8 recover, u8 full_init) e100_sw_reset(bdp, PORT_SELECTIVE_RESET); if (!e100_hw_reset_recover(bdp, PORT_SELECTIVE_RESET)) { - printk(KERN_ERR "e100_deisolate_driver:" + printk(KERN_ERR "e100: e100_deisolate_driver:" " HW reset recover failed\n"); } } @@ -3285,7 +3324,6 @@ e100_deisolate_driver(struct e100_private *bdp, u8 recover, u8 full_init) bdp->driver_isolated = false; } -#ifdef E100_ETHTOOL_IOCTL static int e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr) { @@ -3302,48 +3340,32 @@ e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr) case ETHTOOL_SSET: rc = e100_ethtool_set_settings(dev, ifr); break; -#ifdef ETHTOOL_GDRVINFO case ETHTOOL_GDRVINFO: rc = e100_ethtool_get_drvinfo(dev, ifr); break; -#endif -#ifdef ETHTOOL_NWAY_RST case ETHTOOL_NWAY_RST: rc = e100_ethtool_nway_rst(dev, ifr); break; -#endif -#ifdef ETHTOOL_GLINK case ETHTOOL_GLINK: rc = e100_ethtool_glink(dev, ifr); break; -#endif -#ifdef ETHTOOL_GEEPROM case ETHTOOL_GEEPROM: case ETHTOOL_SEEPROM: rc = e100_ethtool_eeprom(dev, ifr); break; -#endif -#ifdef ETHTOOL_GWOL case ETHTOOL_GWOL: case ETHTOOL_SWOL: rc = e100_ethtool_wol(dev, ifr); break; -#endif -#ifdef ETHTOOL_TEST case ETHTOOL_TEST: rc = e100_ethtool_test(dev, ifr); break; -#endif -#ifdef ETHTOOL_GSTRINGS case ETHTOOL_GSTRINGS: rc = e100_ethtool_gstrings(dev,ifr); break; -#endif -#ifdef ETHTOOL_PHYS_ID case ETHTOOL_PHYS_ID: rc = e100_ethtool_led_blink(dev,ifr); break; -#endif default: break; } //switch @@ -3382,9 +3404,7 @@ e100_ethtool_get_settings(struct net_device *dev, struct ifreq *ifr) } if (bdp->speed_duplex_caps & SUPPORTED_MII) { - spin_lock_bh(&(bdp->mdi_access_lock)); e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &advert); - spin_unlock_bh(&(bdp->mdi_access_lock)); if (advert & ADVERTISE_10HALF) ecmd.advertising |= ADVERTISED_10baseT_Half; @@ -3483,7 +3503,6 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr) return 0; } -#ifdef ETHTOOL_GLINK static int e100_ethtool_glink(struct net_device *dev, struct ifreq *ifr) { @@ -3495,18 +3514,14 @@ e100_ethtool_glink(struct net_device *dev, struct ifreq *ifr) bdp = dev->priv; info.cmd = ETHTOOL_GLINK; - spin_lock_bh(&(bdp->mdi_access_lock)); info.data = e100_get_link_state(bdp); - spin_unlock_bh(&(bdp->mdi_access_lock)); if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) return -EFAULT; return 0; } -#endif -#ifdef ETHTOOL_TEST static int e100_ethtool_test(struct net_device *dev, struct ifreq *ifr) { @@ -3534,9 +3549,7 @@ exit: kfree(info); return rc; } -#endif -#ifdef ETHTOOL_NWAY_RST static int e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr) { @@ -3555,9 +3568,7 @@ e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr) } return 0; } -#endif -#ifdef ETHTOOL_GDRVINFO static int e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr) { @@ -3569,25 +3580,19 @@ e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr) bdp = dev->priv; strncpy(info.driver, e100_short_driver_name, sizeof (info.driver) - 1); - strncpy(info.version, e100_version, sizeof (info.version) - 1); + strncpy(info.version, e100_driver_version, sizeof (info.version) - 1); strncpy(info.fw_version, e100_get_brand_msg(bdp), sizeof (info.fw_version) - 1); strncpy(info.bus_info, bdp->pdev->slot_name, sizeof (info.bus_info) - 1); -#ifdef ETHTOOL_GEEPROM info.eedump_len = (bdp->eeprom_size << 1); -#endif -#ifdef ETHTOOL_TEST info.testinfo_len = E100_MAX_TEST_RES; -#endif if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) return -EFAULT; return 0; } -#endif //ETHTOOL_GDRVINFO -#ifdef ETHTOOL_GEEPROM static int e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr) { @@ -3595,8 +3600,9 @@ e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr) struct ethtool_eeprom ecmd; u16 eeprom_data[256]; u16 *usr_eeprom_ptr; - u16 word_length, word_offset; - int i; + u16 first_word, last_word; + int i, max_len; + void *ptr; if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -3609,48 +3615,56 @@ e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr) usr_eeprom_ptr = (u16 *) (ifr->ifr_data + offsetof(struct ethtool_eeprom, data)); - word_offset = (ecmd.offset >> 1); - if (word_offset >= bdp->eeprom_size) - return -EFAULT; + max_len = bdp->eeprom_size * 2; + if ((ecmd.offset + ecmd.len) > max_len) + ecmd.len = (max_len - ecmd.offset); - word_length = - min_t(u32, (ecmd.len >> 1), (bdp->eeprom_size - word_offset)); + first_word = ecmd.offset >> 1; + last_word = (ecmd.offset + ecmd.len - 1) >> 1; + + if (first_word >= bdp->eeprom_size) + return -EFAULT; if (ecmd.cmd == ETHTOOL_GEEPROM) { - for (i = word_offset; i < (word_length + word_offset); i++) - eeprom_data[i] = e100_eeprom_read(bdp, i); + for(i = 0; i <= (last_word - first_word); i++) + eeprom_data[i] = e100_eeprom_read(bdp, first_word + i); - ecmd.len = (word_length << 1); ecmd.magic = E100_EEPROM_MAGIC; if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) return -EFAULT; - if (copy_to_user(usr_eeprom_ptr, &(eeprom_data[word_offset]), - (ecmd.len << 1))) + if (copy_to_user(usr_eeprom_ptr, eeprom_data, ecmd.len)) return -EFAULT; } else { if (ecmd.magic != E100_EEPROM_MAGIC) return -EFAULT; - if (copy_from_user(&(eeprom_data[word_offset]), usr_eeprom_ptr, - (ecmd.len << 1))) - return -EFAULT; - - e100_eeprom_write_block(bdp, word_offset, - &(eeprom_data[word_offset]), - word_length); + ptr = (void *)eeprom_data; + if(ecmd.offset & 1) { + /* need modification of first changed EEPROM word */ + /* only the second byte of the word is being modified */ + eeprom_data[0] = e100_eeprom_read(bdp, first_word); + ptr++; + } + if((ecmd.offset + ecmd.len) & 1) { + /* need modification of last changed EEPROM word */ + /* only the first byte of the word is being modified */ + eeprom_data[last_word - first_word] = + e100_eeprom_read(bdp, last_word); + } + if(copy_from_user(ptr, usr_eeprom_ptr, ecmd.len)) + return -EFAULT; - ecmd.len = (word_length << 1); + e100_eeprom_write_block(bdp, first_word, eeprom_data, + last_word - first_word + 1); if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) return -EFAULT; } return 0; } -#endif -#ifdef ETHTOOL_PHYS_ID #define E100_BLINK_INTERVAL (HZ/4) /** * e100_led_control @@ -3663,12 +3677,9 @@ e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr) static void e100_led_control(struct e100_private *bdp, u16 led_mdi_op) { - spin_lock_bh(&bdp->mdi_access_lock); - e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL, bdp->phy_addr, led_mdi_op); - spin_unlock_bh(&bdp->mdi_access_lock); } /** * e100_led_blink_callback @@ -3736,7 +3747,6 @@ e100_ethtool_led_blink(struct net_device *dev, struct ifreq *ifr) return 0; } -#endif static inline int __devinit e100_10BaseT_adapter(struct e100_private *bdp) @@ -3785,7 +3795,6 @@ e100_get_speed_duplex_caps(struct e100_private *bdp) } -#ifdef ETHTOOL_GWOL static unsigned char e100_setup_filter(struct e100_private *bdp) { @@ -3818,7 +3827,7 @@ e100_setup_filter(struct e100_private *bdp) res = e100_exec_non_cu_cmd(bdp, cmd); if (!res) - printk(KERN_WARNING "%s Filter setup failed\n", + printk(KERN_WARNING "e100: %s: Filter setup failed\n", bdp->device->name); exit: @@ -3835,9 +3844,9 @@ e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp) if (bdp->wolopts & (WAKE_UCAST | WAKE_ARP)) if (!e100_setup_filter(bdp)) printk(KERN_ERR - "e100_config WOL options failed\n"); + "e100: WOL options failed\n"); } else { - printk(KERN_ERR "e100_config WOL failed\n"); + printk(KERN_ERR "e100: config WOL failed\n"); } } @@ -3899,9 +3908,6 @@ e100_ethtool_wol(struct net_device *dev, struct ifreq *ifr) return res; } -#endif - -#ifdef ETHTOOL_GSTRINGS static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) { struct ethtool_gstrings info; @@ -3944,10 +3950,7 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) kfree(strings); return 0; } -#endif -#endif /*E100_ETHTOOL_IOCTL */ -#ifdef E100_MII_IOCTL static int e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { @@ -3965,10 +3968,8 @@ e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_bh(&(bdp->mdi_access_lock)); e100_mdi_read(bdp, data_ptr->reg_num & 0x1f, bdp->phy_addr, &(data_ptr->val_out)); - spin_unlock_bh(&(bdp->mdi_access_lock)); break; case SIOCSMIIREG: @@ -3977,10 +3978,8 @@ e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (netif_running(dev)) { return -EBUSY; } - spin_lock_bh(&(bdp->mdi_access_lock)); e100_mdi_write(bdp, data_ptr->reg_num & 0x1f, bdp->phy_addr, data_ptr->val_in); - spin_unlock_bh(&(bdp->mdi_access_lock)); break; default: @@ -3988,7 +3987,6 @@ e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } return 0; } -#endif //E100_MII_IOCTL nxmit_cb_entry_t * e100_alloc_non_tx_cmd(struct e100_private *bdp) @@ -4149,17 +4147,22 @@ exit: #ifdef CONFIG_PM static int -e100_save_state(struct pci_dev *pcid, u32 state) +e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) { - struct net_device *dev; - struct e100_private *bdp; - - /* Actually, PCI PM does NOT call this entry */ - if (!(dev = (struct net_device *) pci_get_drvdata(pcid))) - return -1; - bdp = dev->priv; - pci_save_state(pcid, bdp->pci_state); - return 0; + struct pci_dev *pdev = NULL; + switch(event) { + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: + pci_for_each_dev(pdev) { + if(pci_dev_driver(pdev) == &e100_driver) { + /* If net_device struct is allocated? */ + if (pci_get_drvdata(pdev)) + e100_suspend(pdev, 3); + } + } + } + return NOTIFY_DONE; } static int @@ -4169,10 +4172,9 @@ e100_suspend(struct pci_dev *pcid, u32 state) struct e100_private *bdp = netdev->priv; e100_isolate_driver(bdp); - e100_save_state(pcid, state); + pci_save_state(pcid, bdp->pci_state); /* If wol is enabled */ -#ifdef ETHTOOL_GWOL if (bdp->wolopts) { bdp->ip_lbytes = e100_get_ip_lbytes(netdev); e100_do_wol(pcid, bdp); @@ -4183,10 +4185,6 @@ e100_suspend(struct pci_dev *pcid, u32 state) pci_disable_device(pcid); pci_set_power_state(pcid, state); } -#else - pci_disable_device(pcid); - pci_set_power_state(pcid, state); -#endif return 0; } @@ -4207,23 +4205,135 @@ e100_resume(struct pci_dev *pcid) recover = true; } -#ifdef ETHTOOL_GWOL if (bdp->wolopts & (WAKE_UCAST | WAKE_ARP)) { full_init = true; } -#endif e100_deisolate_driver(bdp, recover, full_init); return 0; } -static int -e100_enable_wake(struct pci_dev *pcid, u32 state, int enable) +#endif /* CONFIG_PM */ + +static void +e100_get_mdix_status(struct e100_private *bdp) +{ + if (bdp->rev_id < D102_REV_ID) { + if (netif_carrier_ok(bdp->device)) + bdp->mdix_status = "MDI"; + else + bdp->mdix_status = "None"; + } else { + u16 ctrl_reg; + /* Read the MDIX control register */ + e100_mdi_read(bdp, MII_NCONFIG, bdp->phy_addr, &ctrl_reg); + if (ctrl_reg & MDI_MDIX_CONFIG_IS_OK) { + if (ctrl_reg & MDI_MDIX_STATUS) + bdp->mdix_status = "MDI-X"; + else + bdp->mdix_status = "MDI"; + } else + bdp->mdix_status = "None"; + } +} + +static void +e100_do_hwi(struct net_device *dev) { - /* Driver doesn't need to do anything because it will enable */ - /* wol when suspended. */ - /* Actually, PCI PM does NOT call this entry. */ - return 0; + struct e100_private *bdp = dev->priv; + u16 ctrl_reg; + int distance, open_circut, short_circut; + + e100_mdi_read(bdp, HWI_CONTROL_REG, bdp->phy_addr, &ctrl_reg); + + distance = ctrl_reg & HWI_TEST_DISTANCE; + open_circut = ctrl_reg & HWI_TEST_HIGHZ_PROBLEM; + short_circut = ctrl_reg & HWI_TEST_LOWZ_PROBLEM; + + if ((distance == bdp->saved_distance) && + (open_circut == bdp->saved_open_circut) && + (short_circut == bdp->saved_short_circut)) + bdp->saved_same++; + else { + bdp->saved_same = 0; + bdp->saved_distance = distance; + bdp->saved_open_circut = open_circut; + bdp->saved_short_circut = short_circut; + } + + if (bdp->saved_same == MAX_SAME_RESULTS) { + if ((open_circut && !(short_circut)) || + (!(open_circut) && short_circut)) { + + u8 near_end = ((distance * HWI_REGISTER_GRANULARITY) < + HWI_NEAR_END_BOUNDARY); + if (open_circut) { + if (near_end) + bdp->cable_status = "Open Circut Near End"; + else + bdp->cable_status = "Open Circut Far End"; + } else { + if (near_end) + bdp->cable_status = "Short Circut Near End"; + else + bdp->cable_status = "Short Circut Far End"; + } + goto done; + } + } + else if (bdp->saved_i == HWI_MAX_LOOP) { + bdp->cable_status = "Test failed"; + goto done; + } + + /* Do another hwi test */ + e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr, + (HWI_TEST_ENABLE | HWI_TEST_EXECUTE)); + bdp->saved_i++; + /* relaunch hwi timer in 1 msec */ + mod_timer(&(bdp->hwi_timer), jiffies + (HZ / 1000) ); + return; + +done: + e100_hwi_restore(bdp); + bdp->hwi_started = 0; + return; +} + +static void e100_hwi_restore(struct e100_private *bdp) +{ + u16 control = 0; + + /* Restore speed, duplex and autoneg before */ + /* hwi test, i.e., cable diagnostic */ + + /* Reset hwi test */ + e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr, HWI_RESET_ALL_MASK); + + if ((bdp->params.e100_speed_duplex == E100_AUTONEG) && + (bdp->rev_id >= D102_REV_ID)) + /* Enable MDI/MDI-X auto switching */ + e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, + MDI_MDIX_AUTO_SWITCH_ENABLE); + + switch (bdp->params.e100_speed_duplex) { + case E100_SPEED_10_HALF: + break; + case E100_SPEED_10_FULL: + control = BMCR_FULLDPLX; + break; + case E100_SPEED_100_HALF: + control = BMCR_SPEED100; + break; + case E100_SPEED_100_FULL: + control = BMCR_SPEED100 | BMCR_FULLDPLX; + break; + case E100_AUTONEG: + control = BMCR_ANENABLE | BMCR_ANRESTART; + break; + } + /* Restore original speed/duplex */ + e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control); + return; } -#endif /* CONFIG_PM */ diff --git a/drivers/net/e100/e100_phy.c b/drivers/net/e100/e100_phy.c index 3bd2f620d19a..e4b8c0efec67 100644 --- a/drivers/net/e100/e100_phy.c +++ b/drivers/net/e100/e100_phy.c @@ -96,9 +96,11 @@ e100_mdi_write(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 data) int e100_retry; u32 temp_val; + spin_lock_bh(&bdp->mdi_access_lock); temp_val = (((u32) data) | (reg_addr << 16) | (phy_addr << 21) | (MDI_WRITE << 26)); writel(temp_val, &bdp->scb->scb_mdi_cntrl); + readw(&bdp->scb->scb_status); /* wait 20usec before checking status */ udelay(20); @@ -111,6 +113,7 @@ e100_mdi_write(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 data) udelay(20); e100_retry--; } + spin_unlock_bh(&bdp->mdi_access_lock); } /* @@ -138,9 +141,11 @@ e100_mdi_read(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 *data) int e100_retry; u32 temp_val; + spin_lock_bh(&bdp->mdi_access_lock); /* Issue the read command to the MDI control register. */ temp_val = ((reg_addr << 16) | (phy_addr << 21) | (MDI_READ << 26)); writel(temp_val, &bdp->scb->scb_mdi_cntrl); + readw(&bdp->scb->scb_status); /* wait 20usec before checking status */ udelay(20); @@ -156,6 +161,7 @@ e100_mdi_read(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 *data) // return the lower word *data = (u16) readl(&bdp->scb->scb_mdi_cntrl); + spin_unlock_bh(&bdp->mdi_access_lock); } static unsigned char __devinit @@ -263,21 +269,22 @@ e100_phy_specific_setup(struct e100_private *bdp) case E100_AUTONEG: /* The adapter can't autoneg. so set to 10/HALF */ printk(KERN_INFO - "503 serial component detected which " + "e100: 503 serial component detected which " "cannot autonegotiate\n"); printk(KERN_INFO - "speed/duplex forced to 10Mbps / Half duplex\n"); + "e100: speed/duplex forced to " + "10Mbps / Half duplex\n"); bdp->params.e100_speed_duplex = E100_SPEED_10_HALF; break; case E100_SPEED_100_HALF: case E100_SPEED_100_FULL: printk(KERN_ERR - "503 serial component detected which does not " - "support 100Mbps\n"); + "e100: 503 serial component detected " + "which does not support 100Mbps\n"); printk(KERN_ERR - "Change the forced speed/duplex to a supported " - "setting\n"); + "e100: Change the forced speed/duplex " + "to a supported setting\n"); return false; } @@ -294,7 +301,7 @@ e100_phy_specific_setup(struct e100_private *bdp) if ((bdp->params.e100_speed_duplex != E100_AUTONEG) && (bdp->params.e100_speed_duplex != E100_SPEED_100_FULL)) { /* just inform user about 100 full */ - printk(KERN_ERR "NC3133 NIC can only run " + printk(KERN_ERR "e100: NC3133 NIC can only run " "at 100Mbps full duplex\n"); } @@ -657,8 +664,6 @@ e100_force_speed_duplex(struct e100_private *bdp) bdp->flags |= DF_SPEED_FORCED; - spin_lock_bh(&(bdp->mdi_access_lock)); - e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); control &= ~BMCR_ANENABLE; @@ -702,14 +707,10 @@ e100_force_speed_duplex(struct e100_private *bdp) time_after(jiffies, expires)) { break; } else { - spin_unlock_bh(&(bdp->mdi_access_lock)); yield(); - spin_lock_bh(&(bdp->mdi_access_lock)); } } while (true); - - spin_unlock_bh(&(bdp->mdi_access_lock)); } /* @@ -753,7 +754,12 @@ e100_set_fc(struct e100_private *bdp) if (ad_reg & NWAY_AD_FC_SUPPORTED) bdp->flags |= DF_LINK_FC_CAP; else - bdp->flags &= ~DF_LINK_FC_CAP; + /* If link partner is capable of autoneg, but */ + /* not capable of flow control, Received PAUSE */ + /* frames are still honored, i.e., */ + /* transmitted frames would be paused */ + /* by incoming PAUSE frames */ + bdp->flags |= DF_LINK_FC_TX_ONLY; } else { bdp->flags &= ~DF_LINK_FC_CAP; @@ -821,8 +827,6 @@ e100_auto_neg(struct e100_private *bdp, unsigned char force_restart) bdp->flags &= ~DF_SPEED_FORCED; - spin_lock_bh(&(bdp->mdi_access_lock)); - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); @@ -848,25 +852,30 @@ e100_auto_neg(struct e100_private *bdp, unsigned char force_restart) time_after(jiffies, expires) ) { goto exit; } else { - spin_unlock_bh(&(bdp->mdi_access_lock)); yield(); - spin_lock_bh(&(bdp->mdi_access_lock)); } } while (true); } exit: e100_find_speed_duplex(bdp); - spin_unlock_bh(&(bdp->mdi_access_lock)); } void e100_phy_set_speed_duplex(struct e100_private *bdp, unsigned char force_restart) { if (bdp->params.e100_speed_duplex == E100_AUTONEG) { + if (bdp->rev_id >= D102_REV_ID) + /* Enable MDI/MDI-X auto switching */ + e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, + MDI_MDIX_AUTO_SWITCH_ENABLE); e100_auto_neg(bdp, force_restart); } else { + if (bdp->rev_id >= D102_REV_ID) + /* Disable MDI/MDI-X auto switching */ + e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, + MDI_MDIX_RESET_ALL_MASK); e100_force_speed_duplex(bdp); } diff --git a/drivers/net/e100/e100_phy.h b/drivers/net/e100/e100_phy.h index 1a8166e264fa..4d05de89b4e7 100644 --- a/drivers/net/e100/e100_phy.h +++ b/drivers/net/e100/e100_phy.h @@ -124,6 +124,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define NSC_CONG_CONTROL_REG 0x17 /* National (TX) congestion control */ #define NSC_SPEED_IND_REG 0x19 /* National (TX) speed indication */ +#define HWI_CONTROL_REG 0x1D /* HWI Control register */ +/* MDI/MDI-X Control Register bit definitions */ +#define MDI_MDIX_RES_TIMER BIT_0_3 /* minimum slot time for resolution timer */ +#define MDI_MDIX_CONFIG_IS_OK BIT_4 /* 1 = resolution algorithm completes OK */ +#define MDI_MDIX_STATUS BIT_5 /* 1 = MDIX (croos over), 0 = MDI (straight through) */ +#define MDI_MDIX_SWITCH BIT_6 /* 1 = Forces to MDIX, 0 = Forces to MDI */ +#define MDI_MDIX_AUTO_SWITCH_ENABLE BIT_7 /* 1 = MDI/MDI-X feature enabled */ +#define MDI_MDIX_CONCT_CONFIG BIT_8 /* Sets the MDI/MDI-X connectivity configuration (test prupose only) */ +#define MDI_MDIX_CONCT_TEST_ENABLE BIT_9 /* 1 = Enables connectivity testing */ +#define MDI_MDIX_RESET_ALL_MASK 0x0000 + +/* HWI Control Register bit definitions */ +#define HWI_TEST_DISTANCE BIT_0_8 /* distance to cable problem */ +#define HWI_TEST_HIGHZ_PROBLEM BIT_9 /* 1 = Open Circuit */ +#define HWI_TEST_LOWZ_PROBLEM BIT_10 /* 1 = Short Circuit */ +#define HWI_TEST_RESERVED (BIT_11 | BIT_12) /* reserved */ +#define HWI_TEST_EXECUTE BIT_13 /* 1 = Execute the HWI test on the PHY */ +#define HWI_TEST_ABILITY BIT_14 /* 1 = test passed */ +#define HWI_TEST_ENABLE BIT_15 /* 1 = Enables the HWI feature */ +#define HWI_RESET_ALL_MASK 0x0000 + /* ############Start of 82555 specific defines################## */ /* Intel 82555 specific registers */ diff --git a/drivers/net/e100/e100_proc.c b/drivers/net/e100/e100_proc.c index a589557b6a4e..fd029e1b0150 100644 --- a/drivers/net/e100/e100_proc.c +++ b/drivers/net/e100/e100_proc.c @@ -91,11 +91,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <linux/config.h> -#ifndef CONFIG_PROC_FS -#undef E100_CONFIG_PROC_FS -#endif - -#ifdef E100_CONFIG_PROC_FS +#ifdef CONFIG_PROC_FS #include "e100.h" /* MDI sleep time is at least 50 ms, in jiffies */ #define MDI_SLEEP_TIME ((HZ / 20) + 1) @@ -106,8 +102,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static struct proc_dir_entry *adapters_proc_dir = 0; /* externs from e100_main.c */ -extern const char *e100_short_driver_name; -extern const char *e100_version; +extern char e100_short_driver_name[]; +extern char e100_driver_version[]; extern struct net_device_stats *e100_get_stats(struct net_device *dev); extern char *e100_get_brand_msg(struct e100_private *bdp); extern void e100_mdi_write(struct e100_private *, u32, u32, u16); @@ -115,8 +111,6 @@ extern void e100_mdi_write(struct e100_private *, u32, u32, u16); static void e100_proc_cleanup(void); static unsigned char e100_init_proc_dir(void); -#define E100_EOU - #define ADAPTERS_PROC_DIR "PRO_LAN_Adapters" #define WRITE_BUF_MAX_LEN 20 #define READ_BUF_MAX_LEN 256 @@ -191,7 +185,7 @@ read_descr(char *page, char **start, off_t off, int count, int *eof, void *data) struct e100_private *bdp = data; int len; - len = sprintf(page, "%s\n", e100_get_brand_msg(bdp)); + len = sprintf(page, "%s\n", bdp->id_string); return generic_read(page, start, off, count, eof, len); } @@ -223,23 +217,15 @@ read_part_number(char *page, char **start, off_t off, static void set_led(struct e100_private *bdp, u16 led_mdi_op) { - spin_lock_bh(&bdp->mdi_access_lock); - e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL, bdp->phy_addr, led_mdi_op); - spin_unlock_bh(&bdp->mdi_access_lock); - set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(MDI_SLEEP_TIME); - spin_lock_bh(&bdp->mdi_access_lock); - /* turn led ownership to the chip */ e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL, bdp->phy_addr, PHY_82555_LED_NORMAL_CONTROL); - - spin_unlock_bh(&bdp->mdi_access_lock); } static int @@ -350,335 +336,6 @@ read_info(char *page, char **start, off_t off, int count, int *eof, void *data) return generic_read(page, start, off, count, eof, len); } -#ifdef E100_EOU -/********************** - * parameter entries - **********************/ -static int -read_int_param(char *page, char *name, char *desc, int def, int min, int max) -{ - int len; - - len = sprintf(page, "Name: %s\n", name); - len += sprintf(page + len, "Description: %s\n", desc); - len += sprintf(page + len, "Default_Value: %d\n", def); - len += sprintf(page + len, "Type: Range\n"); - len += sprintf(page + len, "Min: %d\n", min); - len += sprintf(page + len, "Max: %d\n", max); - len += sprintf(page + len, "Step:1\n"); - len += sprintf(page + len, "Radix: dec\n"); - - return len; -} - -static int -read_bool_param(char *page, char *name, char *desc, int def) -{ - int len; - - len = sprintf(page, "Name: %s\n", name); - len += sprintf(page + len, "Description: %s\n", desc); - len += sprintf(page + len, "Default_Value: %d\n", def); - len += sprintf(page + len, "Type: Enum\n"); - len += sprintf(page + len, "0: Off\n"); - len += sprintf(page + len, "1: On\n"); - - return len; -} - -static int -read_speed_duplex_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = sprintf(page, "Name: Speed and Duplex\n"); - len += sprintf(page + len, "Description: Sets the adapter's " - "speed and duplex mode\n"); - len += sprintf(page + len, "Default_Value: 0\n"); - len += sprintf(page + len, "Type: Enum\n"); - len += sprintf(page + len, "0: Auto-Negotiate\n"); - len += sprintf(page + len, "1: 10 Mbps / Half Duplex\n"); - len += sprintf(page + len, "2: 10 Mbps / Full Duplex\n"); - len += sprintf(page + len, "3: 100 Mbps / Half Duplex\n"); - len += sprintf(page + len, "4: 100 Mbps / Full Duplex\n"); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_tx_desc_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_int_param(page, "Transmit Descriptors", - "Sets the number of Tx descriptors " - "available for the adapter", - E100_DEFAULT_TCB, E100_MIN_TCB, E100_MAX_TCB); - return generic_read(page, start, off, count, eof, len); -} - -static int -read_rx_desc_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_int_param(page, "Receive Descriptors", - "Sets the number of Rx descriptors " - "available for the adapter", - E100_DEFAULT_RFD, E100_MIN_RFD, E100_MAX_RFD); - return generic_read(page, start, off, count, eof, len); -} - -static int -read_ber_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_int_param(page, "Bit Error Rate", - "Sets the value for the BER correction algorithm", - E100_DEFAULT_BER, 0, ZLOCK_MAX_ERRORS); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_xsum_rx_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_bool_param(page, "RX Checksum", - "Setting this value to \"On\" enables " - "receive checksum", E100_DEFAULT_XSUM); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_ucode_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_bool_param(page, "Microcode", - "Setting this value to \"On\" enables " - "the adapter's microcode", E100_DEFAULT_UCODE); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_bundle_small_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_bool_param(page, "Bundle Small Frames", - "Setting this value to \"On\" enables " - "interrupt bundling of small frames", - E100_DEFAULT_BUNDLE_SMALL_FR); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_fc_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_bool_param(page, "Flow Control", - "Setting this value to \"On\" enables processing " - "flow-control packets", E100_DEFAULT_FC); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_rcv_cong_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_bool_param(page, "Receive Congestion Control", - "Setting this value to \"On\" enables switching " - "to polling mode on receive", - E100_DEFAULT_RX_CONGESTION_CONTROL); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_poll_max_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct e100_private *bdp = data; - - int len; - - len = read_int_param(page, "Maximum Polling Work", - "Sets the max number of RX packets processed" - " by single polling function call", - bdp->params.RxDescriptors, 1, E100_MAX_RFD); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_int_delay_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_int_param(page, "CPU Saver Interrupt Delay", - "Sets the value for CPU saver's interrupt delay", - E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY, 0x0, - 0xFFFF); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_bundle_max_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_int_param(page, "CPU Saver Maximum Bundle", - "Sets CPU saver's maximum value", - E100_DEFAULT_CPUSAVER_BUNDLE_MAX, 0x1, 0xFFFF); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_ifs_def(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = read_bool_param(page, "IFS", - "Setting this value to \"On\" enables " - "the adaptive IFS algorithm", E100_DEFAULT_IFS); - - return generic_read(page, start, off, count, eof, len); -} - -static int -read_xsum_rx_val(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct e100_private *bdp = data; - unsigned long val; - - val = (bdp->params.b_params & PRM_XSUMRX) ? 1 : 0; - return read_ulong(page, start, off, count, eof, val); -} - -static int -read_ucode_val(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct e100_private *bdp = data; - unsigned long val; - - val = (bdp->params.b_params & PRM_UCODE) ? 1 : 0; - return read_ulong(page, start, off, count, eof, val); -} - -static int -read_fc_val(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct e100_private *bdp = data; - unsigned long val; - - val = (bdp->params.b_params & PRM_FC) ? 1 : 0; - return read_ulong(page, start, off, count, eof, val); -} - -static int -read_ifs_val(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct e100_private *bdp = data; - unsigned long val; - - val = (bdp->params.b_params & PRM_IFS) ? 1 : 0; - return read_ulong(page, start, off, count, eof, val); -} - -static int -read_bundle_small_val(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct e100_private *bdp = data; - unsigned long val; - - val = (bdp->params.b_params & PRM_BUNDLE_SMALL) ? 1 : 0; - return read_ulong(page, start, off, count, eof, val); -} - -static int -read_rcv_cong_val(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct e100_private *bdp = data; - unsigned long val; - - val = (bdp->params.b_params & PRM_RX_CONG) ? 1 : 0; - return read_ulong(page, start, off, count, eof, val); -} - -static int -read_gen_prm(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int val = 0; - - if (data) - val = *((int *) data); - - return read_ulong(page, start, off, count, eof, (unsigned long) val); -} - -static e100_proc_entry e100_proc_params[] = { - /* definitions */ - {"e100_speed_duplex.def", read_speed_duplex_def, 0, 0}, - {"RxDescriptors.def", read_rx_desc_def, 0, 0}, - {"TxDescriptors.def", read_tx_desc_def, 0, 0}, - {"XsumRX.def", read_xsum_rx_def, 0, 0}, - {"ucode.def", read_ucode_def, 0, 0}, - {"BundleSmallFr.def", read_bundle_small_def, 0, 0}, - {"IntDelay.def", read_int_delay_def, 0, 0}, - {"BundleMax.def", read_bundle_max_def, 0, 0}, - {"ber.def", read_ber_def, 0, 0}, - {"flow_control.def", read_fc_def, 0, 0}, - {"IFS.def", read_ifs_def, 0, 0}, - {"RxCongestionControl.def", read_rcv_cong_def, 0, 0}, - {"PollingMaxWork.def", read_poll_max_def, 0, 0}, - /* values */ - {"e100_speed_duplex.val", read_gen_prm, 0, bdp_prm_off(e100_speed_duplex)}, - {"RxDescriptors.val", read_gen_prm, 0, bdp_prm_off(RxDescriptors)}, - {"TxDescriptors.val", read_gen_prm, 0, bdp_prm_off(TxDescriptors)}, - {"XsumRX.val", read_xsum_rx_val, 0, 0}, - {"ucode.val", read_ucode_val, 0, 0}, - {"BundleSmallFr.val", read_bundle_small_val, 0, 0}, - {"IntDelay.val", read_gen_prm, 0, bdp_prm_off(IntDelay)}, - {"BundleMax.val", read_gen_prm, 0, bdp_prm_off(BundleMax)}, - {"ber.val", read_gen_prm, 0, bdp_prm_off(ber)}, - {"flow_control.val", read_fc_val, 0, 0}, - {"IFS.val", read_ifs_val, 0, 0}, - {"RxCongestionControl.val", read_rcv_cong_val, 0, 0}, - {"PollingMaxWork.val", read_gen_prm, 0, bdp_prm_off(PollingMaxWork)}, - {"", 0, 0, 0} -}; -#endif /* E100_EOU */ - static struct proc_dir_entry * __devinit create_proc_rw(char *name, void *data, struct proc_dir_entry *parent, read_proc_t * read_proc, write_proc_t * write_proc) @@ -705,58 +362,6 @@ create_proc_rw(char *name, void *data, struct proc_dir_entry *parent, return pdep; } -#ifdef E100_EOU -static int __devinit -create_proc_param_subdir(struct e100_private *bdp, - struct proc_dir_entry *dev_dir) -{ - struct proc_dir_entry *param_dir; - e100_proc_entry *pe; - void *data; - - param_dir = create_proc_entry("LoadParameters", S_IFDIR, dev_dir); - if (!param_dir) - return -ENOMEM; - - for (pe = e100_proc_params; pe->name[0]; pe++) { - - data = ((char *) bdp) + pe->offset; - - if (!(create_proc_rw(pe->name, data, param_dir, - pe->read_proc, pe->write_proc))) { - return -ENOMEM; - } - } - - return 0; -} - -static void -remove_proc_param_subdir(struct proc_dir_entry *parent) -{ - struct proc_dir_entry *de; - e100_proc_entry *pe; - int len; - - len = strlen("LoadParameters"); - - for (de = parent->subdir; de; de = de->next) { - if ((de->namelen == len) && - (!memcmp(de->name, "LoadParameters", len))) - break; - } - - if (!de) - return; - - for (pe = e100_proc_params; pe->name[0]; pe++) { - remove_proc_entry(pe->name, de); - } - - remove_proc_entry("LoadParameters", parent); -} -#endif /* E100_EOU */ - void e100_remove_proc_subdir(struct e100_private *bdp) { @@ -781,9 +386,6 @@ e100_remove_proc_subdir(struct e100_private *bdp) remove_proc_entry(pe->name, bdp->proc_parent); } -#ifdef E100_EOU - remove_proc_param_subdir(bdp->proc_parent); -#endif remove_proc_entry(bdp->device->name, adapters_proc_dir); bdp->proc_parent = NULL; } @@ -844,13 +446,6 @@ e100_create_proc_subdir(struct e100_private *bdp) } } -#ifdef E100_EOU - if (create_proc_param_subdir(bdp, dev_dir)) { - e100_remove_proc_subdir(bdp); - return -ENOMEM; - } -#endif - return 0; } diff --git a/drivers/net/e100/e100_test.c b/drivers/net/e100/e100_test.c index b2fcf25ea88b..3afac1730f55 100644 --- a/drivers/net/e100/e100_test.c +++ b/drivers/net/e100/e100_test.c @@ -72,7 +72,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "e100.h" #include "e100_config.h" -#ifdef ETHTOOL_TEST extern u16 e100_eeprom_read(struct e100_private *, u16); extern int e100_wait_exec_cmplx(struct e100_private *, u32,u8); @@ -380,11 +379,11 @@ e100_diag_loopback_cu_ru_exec(struct e100_private *bdp) { /*load CU & RU base */ if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE)) - printk("@@@ SCB_CUC_LOAD_BASE failed\n"); + printk("e100: SCB_CUC_LOAD_BASE failed\n"); if(!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE)) - printk("@@@ SCB_RUC_LOAD_BASE failed!\n"); + printk("e100: SCB_RUC_LOAD_BASE failed!\n"); if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START)) - printk("@@@ SCB_RUC_START failed!\n"); + printk("e100: SCB_RUC_START failed!\n"); bdp->next_cu_cmd = START_WAIT; e100_start_cu(bdp, bdp->loopback.tcb); @@ -457,5 +456,3 @@ e100_diag_loopback_free (struct e100_private *bdp) bdp->loopback.dma_handle); } -#endif - diff --git a/drivers/net/e100/e100_vendor.h b/drivers/net/e100/e100_vendor.h index c8f65af93914..21580737b865 100644 --- a/drivers/net/e100/e100_vendor.h +++ b/drivers/net/e100/e100_vendor.h @@ -125,6 +125,7 @@ enum e100_device_type { E100_82559_LOM, E100_82559_LOM_AOL, E100_82559_LOM_AOL2, + E100_82559_LOM_DELL, E100_IBM_MDS, E100_CMPQ_S, E100_PROVE_DA, @@ -132,7 +133,8 @@ enum e100_device_type { E100_PROVE_LOM, E100_PROVE_NET, E100_82562, - E100_ALL_BOARDS, + E100_82551QM, + E100_ALL_BOARDS }; struct e100_vendor_info e100_vendor_info_array[] = { @@ -147,6 +149,7 @@ struct e100_vendor_info e100_vendor_info_array[] = { { E100_BRD_100, "Intel(R) PRO/100+ PCI Adapter"}, { E100_BRD_100M, "Intel(R) PRO/100+ Management Adapter"}, { E100_BRD_AOL2, "Intel(R) PRO/100+ Alert on LAN* 2 Management Adapter"}, + { E100_82559_LOM_DELL, "Intel(R) 8255x Based Network Connection"}, { E100_BRD_AOL, "Intel(R) PRO/100+ Alert on LAN* Management Adapter"}, { E100_PROS_M, "Intel(R) PRO/100 S Management Adapter"}, { E100_PROS_AM, "Intel(R) PRO/100 S Advanced Management Adapter"}, @@ -186,6 +189,7 @@ struct e100_vendor_info e100_vendor_info_array[] = { { E100_PROVE_LOM, "Intel(R) PRO/100 VE Network ConnectionPLC LOM" }, { E100_PROVE_NET, "Intel(R) PRO/100 VE Network Connection"}, { E100_82562, "Intel(R)82562 based Fast Ethernet Connection"}, + { E100_82551QM, "Intel(R) PRO/100 M Mobile Connection"}, { E100_ALL_BOARDS, "Intel(R) 8255x-based Ethernet Adapter"}, {0,NULL} }; @@ -309,6 +313,7 @@ static struct pci_device_id e100_id_table[] __devinitdata = { {0x8086, 0x1229, 0x0E11, 0xB144, 0, 0, E100_CMPQ_S}, {0x8086, 0x1229, 0x0E11, 0xB163, 0, 0, E100_CMPQ_S}, {0x8086, 0x1229, 0x0E11, 0xB164, 0, 0, E100_CMPQ_S}, + {0x8086, 0x1229, 0x1028, PCI_ANY_ID, 0, 0, E100_82559_LOM_DELL}, {0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, {0x8086, 0x2449, 0x1014, 0x0265, 0, 0, E100_PROVE_D}, @@ -324,7 +329,11 @@ static struct pci_device_id e100_id_table[] __devinitdata = { {0x8086, 0x2449, 0x0E11, PCI_ANY_ID, 0, 0, E100_PROVM_NET}, {0x8086, 0x2449, 0x1014, PCI_ANY_ID, 0, 0, E100_PROVE_D}, {0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, - + + {0x8086, 0x1059, 0x1179, 0x0005, 0, 0, E100_82551QM}, + {0x8086, 0x1059, 0x1033, 0x8191, 0, 0, E100_82551QM}, + {0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_82551QM}, + {0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, {0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, {0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 197222a539de..c108dd69b1e8 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -109,11 +109,11 @@ #include <linux/list.h> #include <linux/reboot.h> #include <linux/ethtool.h> -#ifdef NETIF_F_HW_VLAN_TX #include <linux/if_vlan.h> -#endif #define BAR_0 0 +#define BAR_1 1 +#define BAR_5 5 #define PCI_DMA_64BIT 0xffffffffffffffffULL #define PCI_DMA_32BIT 0x00000000ffffffffULL @@ -150,6 +150,8 @@ struct e1000_adapter; #define E1000_JUMBO_PBA 0x00000028 #define E1000_DEFAULT_PBA 0x00000030 +#define AUTO_ALL_MODES 0 + /* only works for sizes that are powers of 2 */ #define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) @@ -195,9 +197,7 @@ struct e1000_adapter { #ifdef CONFIG_PROC_FS struct list_head proc_list_head; #endif -#ifdef NETIF_F_HW_VLAN_TX struct vlan_group *vlgrp; -#endif char *id_string; uint32_t bd_number; uint32_t rx_buffer_len; @@ -208,10 +208,8 @@ struct e1000_adapter { spinlock_t stats_lock; atomic_t irq_sem; -#ifdef ETHTOOL_PHYS_ID struct timer_list blink_timer; unsigned long led_status; -#endif /* TX */ struct e1000_desc_ring tx_ring; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 044958ed25a2..63227faf62a1 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -249,17 +249,70 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter, struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff) { struct e1000_hw *hw = &adapter->hw; - int i, max_len; + int i, max_len, first_word, last_word; + + if(eeprom->len == 0) return; eeprom->magic = hw->vendor_id | (hw->device_id << 16); max_len = e1000_eeprom_size(hw); - if ((eeprom->offset + eeprom->len) > max_len) + if((eeprom->offset + eeprom->len) > max_len) eeprom->len = (max_len - eeprom->offset); - for(i = 0; i < (max_len >> 1); i++) - e1000_read_eeprom(&adapter->hw, i, &eeprom_buff[i]); + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + + for(i = 0; i <= (last_word - first_word); i++) + e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]); +} + +static int +e1000_ethtool_seeprom(struct e1000_adapter *adapter, + struct ethtool_eeprom *eeprom, void *user_data) +{ + struct e1000_hw *hw = &adapter->hw; + uint16_t eeprom_buff[256]; + int i, max_len, first_word, last_word; + void *ptr; + + if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) + return -EFAULT; + + if(eeprom->len == 0) return 0; + + max_len = e1000_eeprom_size(hw); + + if((eeprom->offset + eeprom->len) > max_len) + eeprom->len = (max_len - eeprom->offset); + + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + ptr = (void *)eeprom_buff; + + if(eeprom->offset & 1) { + /* need read/modify/write of first changed EEPROM word */ + /* only the second byte of the word is being modified */ + e1000_read_eeprom(hw, first_word, &eeprom_buff[0]); + ptr++; + } + if((eeprom->offset + eeprom->len) & 1) { + /* need read/modify/write of last changed EEPROM word */ + /* only the first byte of the word is being modified */ + e1000_read_eeprom(hw, last_word, + &eeprom_buff[last_word - first_word]); + } + if(copy_from_user(ptr, user_data, eeprom->len)) + return -EFAULT; + + for(i = 0; i <= (last_word - first_word); i++) + e1000_write_eeprom(hw, first_word + i, eeprom_buff[i]); + + /* Update the checksum over the first part of the EEPROM if needed */ + if(first_word <= EEPROM_CHECKSUM_REG) + e1000_update_eeprom_checksum(hw); + + return 0; } static void @@ -339,7 +392,7 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82546EB_COPPER: - if(wol->wolopts & WAKE_ARP) + if(wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; adapter->wol = 0; @@ -359,7 +412,6 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) return 0; } -#ifdef ETHTOOL_PHYS_ID /* toggle LED 4 times per second = 2 "blinks" per second */ #define E1000_ID_INTERVAL (HZ/4) @@ -405,7 +457,6 @@ e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id) return 0; } -#endif /* ETHTOOL_PHYS_ID */ int e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) @@ -463,14 +514,12 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) e1000_up(adapter); return 0; } -#ifdef ETHTOOL_PHYS_ID case ETHTOOL_PHYS_ID: { struct ethtool_value id; if(copy_from_user(&id, addr, sizeof(id))) return -EFAULT; return e1000_ethtool_led_blink(adapter, &id); } -#endif /* ETHTOOL_PHYS_ID */ case ETHTOOL_GLINK: { struct ethtool_value link = {ETHTOOL_GLINK}; link.data = netif_carrier_ok(netdev); @@ -496,6 +545,7 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) case ETHTOOL_GEEPROM: { struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM}; uint16_t eeprom_buff[256]; + void *ptr; if(copy_from_user(&eeprom, addr, sizeof(eeprom))) return -EFAULT; @@ -506,11 +556,24 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) return -EFAULT; addr += offsetof(struct ethtool_eeprom, data); + ptr = ((void *)eeprom_buff) + (eeprom.offset & 1); - if(copy_to_user(addr, eeprom_buff + eeprom.offset, eeprom.len)) + if(copy_to_user(addr, ptr, eeprom.len)) return -EFAULT; return 0; } + case ETHTOOL_SEEPROM: { + struct ethtool_eeprom eeprom; + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + + if(copy_from_user(&eeprom, addr, sizeof(eeprom))) + return -EFAULT; + + addr += offsetof(struct ethtool_eeprom, data); + return e1000_ethtool_seeprom(adapter, &eeprom, addr); + } default: return -EOPNOTSUPP; } diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 38ea8c10ca8e..4b7c41720f84 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -107,17 +107,13 @@ e1000_reset_hw(struct e1000_hw *hw) uint32_t ctrl_ext; uint32_t icr; uint32_t manc; - uint16_t pci_cmd_word; DEBUGFUNC("e1000_reset_hw"); /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ if(hw->mac_type == e1000_82542_rev2_0) { - if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) { - DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); - pci_cmd_word = hw->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE; - e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &pci_cmd_word); - } + DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); + e1000_pci_clear_mwi(hw); } /* Clear interrupt mask to stop board from generating interrupts */ @@ -130,6 +126,7 @@ e1000_reset_hw(struct e1000_hw *hw) */ E1000_WRITE_REG(hw, RCTL, 0); E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP); + E1000_WRITE_FLUSH(hw); /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ hw->tbi_compatibility_on = FALSE; @@ -146,7 +143,11 @@ e1000_reset_hw(struct e1000_hw *hw) */ DEBUGOUT("Issuing a global reset to MAC\n"); ctrl = E1000_READ_REG(hw, CTRL); - E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); + + if(hw->mac_type > e1000_82543) + E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); + else + E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); /* Force a reload from the EEPROM if necessary */ if(hw->mac_type < e1000_82540) { @@ -155,6 +156,7 @@ e1000_reset_hw(struct e1000_hw *hw) ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_EE_RST; E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); /* Wait for EEPROM reload */ msec_delay(2); } else { @@ -176,7 +178,7 @@ e1000_reset_hw(struct e1000_hw *hw) /* If MWI was previously enabled, reenable it. */ if(hw->mac_type == e1000_82542_rev2_0) { if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) - e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &hw->pci_cmd_word); + e1000_pci_set_mwi(hw); } } @@ -197,7 +199,6 @@ e1000_init_hw(struct e1000_hw *hw) uint32_t ctrl, status; uint32_t i; int32_t ret_val; - uint16_t pci_cmd_word; uint16_t pcix_cmd_word; uint16_t pcix_stat_hi_word; uint16_t cmd_mmrbc; @@ -240,12 +241,10 @@ e1000_init_hw(struct e1000_hw *hw) /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ if(hw->mac_type == e1000_82542_rev2_0) { - if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) { - DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); - pci_cmd_word = hw->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE; - e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &pci_cmd_word); - } + DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); + e1000_pci_clear_mwi(hw); E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST); + E1000_WRITE_FLUSH(hw); msec_delay(5); } @@ -257,9 +256,10 @@ e1000_init_hw(struct e1000_hw *hw) /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ if(hw->mac_type == e1000_82542_rev2_0) { E1000_WRITE_REG(hw, RCTL, 0); + E1000_WRITE_FLUSH(hw); msec_delay(1); if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) - e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &hw->pci_cmd_word); + e1000_pci_set_mwi(hw); } /* Zero out the Multicast HASH table */ @@ -505,6 +505,7 @@ e1000_setup_fiber_link(struct e1000_hw *hw) E1000_WRITE_REG(hw, TXCW, txcw); E1000_WRITE_REG(hw, CTRL, ctrl); + E1000_WRITE_FLUSH(hw); hw->txcw = txcw; msec_delay(1); @@ -1118,6 +1119,7 @@ e1000_config_collision_dist(struct e1000_hw *hw) tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; E1000_WRITE_REG(hw, TCTL, tctl); + E1000_WRITE_FLUSH(hw); } /****************************************************************************** @@ -1715,6 +1717,7 @@ e1000_raise_mdi_clk(struct e1000_hw *hw, * bit), and then delay 2 microseconds. */ E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC)); + E1000_WRITE_FLUSH(hw); usec_delay(2); } @@ -1732,6 +1735,7 @@ e1000_lower_mdi_clk(struct e1000_hw *hw, * bit), and then delay 2 microseconds. */ E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC)); + E1000_WRITE_FLUSH(hw); usec_delay(2); } @@ -1774,6 +1778,7 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw, else ctrl &= ~E1000_CTRL_MDIO; E1000_WRITE_REG(hw, CTRL, ctrl); + E1000_WRITE_FLUSH(hw); usec_delay(2); @@ -1782,9 +1787,6 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw, mask = mask >> 1; } - - /* Clear the data bit just before leaving this routine. */ - ctrl &= ~E1000_CTRL_MDIO; } /****************************************************************************** @@ -1815,6 +1817,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw) ctrl &= ~E1000_CTRL_MDIO; E1000_WRITE_REG(hw, CTRL, ctrl); + E1000_WRITE_FLUSH(hw); /* Raise and Lower the clock before reading in the data. This accounts for * the turnaround bits. The first clock occurred when we clocked out the @@ -1835,9 +1838,6 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw) e1000_raise_mdi_clk(hw, &ctrl); e1000_lower_mdi_clk(hw, &ctrl); - /* Clear the MDIO bit just before leaving this routine. */ - ctrl &= ~E1000_CTRL_MDIO; - return data; } @@ -2011,8 +2011,10 @@ e1000_phy_hw_reset(struct e1000_hw *hw) */ ctrl = E1000_READ_REG(hw, CTRL); E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); + E1000_WRITE_FLUSH(hw); msec_delay(10); E1000_WRITE_REG(hw, CTRL, ctrl); + E1000_WRITE_FLUSH(hw); } else { /* Read the Extended Device Control Register, assert the PHY_RESET_DIR * bit to put the PHY into reset. Then, take it out of reset. @@ -2021,9 +2023,11 @@ e1000_phy_hw_reset(struct e1000_hw *hw) ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); msec_delay(10); ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); } usec_delay(150); } @@ -2226,6 +2230,7 @@ e1000_raise_ee_clk(struct e1000_hw *hw, */ *eecd = *eecd | E1000_EECD_SK; E1000_WRITE_REG(hw, EECD, *eecd); + E1000_WRITE_FLUSH(hw); usec_delay(50); } @@ -2244,6 +2249,7 @@ e1000_lower_ee_clk(struct e1000_hw *hw, */ *eecd = *eecd & ~E1000_EECD_SK; E1000_WRITE_REG(hw, EECD, *eecd); + E1000_WRITE_FLUSH(hw); usec_delay(50); } @@ -2281,6 +2287,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw, eecd |= E1000_EECD_DI; E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); usec_delay(50); @@ -2375,24 +2382,71 @@ e1000_standby_eeprom(struct e1000_hw *hw) /* Deselct EEPROM */ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); usec_delay(50); /* Clock high */ eecd |= E1000_EECD_SK; E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); usec_delay(50); /* Select EEPROM */ eecd |= E1000_EECD_CS; E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); usec_delay(50); /* Clock low */ eecd &= ~E1000_EECD_SK; E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); usec_delay(50); } +/****************************************************************************** + * Raises then lowers the EEPROM's clock pin + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static void +e1000_clock_eeprom(struct e1000_hw *hw) +{ + uint32_t eecd; + + eecd = E1000_READ_REG(hw, EECD); + + /* Rising edge of clock */ + eecd |= E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + usec_delay(50); + + /* Falling edge of clock */ + eecd &= ~E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + usec_delay(50); +} + +/****************************************************************************** + * Terminates a command by lowering the EEPROM's chip select pin + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static void +e1000_cleanup_eeprom(struct e1000_hw *hw) +{ + uint32_t eecd; + + eecd = E1000_READ_REG(hw, EECD); + + eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); + + E1000_WRITE_REG(hw, EECD, eecd); + + e1000_clock_eeprom(hw); +} /****************************************************************************** * Reads a 16 bit word from the EEPROM. @@ -2495,6 +2549,152 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw) } /****************************************************************************** + * Calculates the EEPROM checksum and writes it to the EEPROM + * + * hw - Struct containing variables accessed by shared code + * + * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. + * Writes the difference to word offset 63 of the EEPROM. + *****************************************************************************/ +int32_t +e1000_update_eeprom_checksum(struct e1000_hw *hw) +{ + uint16_t checksum = 0; + uint16_t i, eeprom_data; + + DEBUGFUNC("e1000_update_eeprom_checksum"); + + for(i = 0; i < EEPROM_CHECKSUM_REG; i++) { + if(e1000_read_eeprom(hw, i, &eeprom_data) < 0) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } + checksum += eeprom_data; + } + checksum = (uint16_t) EEPROM_SUM - checksum; + if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum) < 0) { + DEBUGOUT("EEPROM Write Error\n"); + return -E1000_ERR_EEPROM; + } + return 0; +} + +/****************************************************************************** + * Writes a 16 bit word to a given offset in the EEPROM. + * + * hw - Struct containing variables accessed by shared code + * offset - offset within the EEPROM to be written to + * data - 16 bit word to be writen to the EEPROM + * + * If e1000_update_eeprom_checksum is not called after this function, the + * EEPROM will most likely contain an invalid checksum. + *****************************************************************************/ +int32_t +e1000_write_eeprom(struct e1000_hw *hw, + uint16_t offset, + uint16_t data) +{ + uint32_t eecd; + uint32_t i = 0; + int32_t status = 0; + boolean_t large_eeprom = FALSE; + + DEBUGFUNC("e1000_write_eeprom"); + + /* Request EEPROM Access */ + if(hw->mac_type > e1000_82544) { + eecd = E1000_READ_REG(hw, EECD); + if(eecd & E1000_EECD_SIZE) large_eeprom = TRUE; + eecd |= E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + eecd = E1000_READ_REG(hw, EECD); + while((!(eecd & E1000_EECD_GNT)) && (i < 100)) { + i++; + usec_delay(5); + eecd = E1000_READ_REG(hw, EECD); + } + if(!(eecd & E1000_EECD_GNT)) { + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + DEBUGOUT("Could not acquire EEPROM grant\n"); + return -E1000_ERR_EEPROM; + } + } + + /* Prepare the EEPROM for writing */ + e1000_setup_eeprom(hw); + + /* Send the 9-bit (or 11-bit on large EEPROM) EWEN (write enable) command + * to the EEPROM (5-bit opcode plus 4/6-bit dummy). This puts the EEPROM + * into write/erase mode. + */ + e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE, 5); + if(large_eeprom) + e1000_shift_out_ee_bits(hw, 0, 6); + else + e1000_shift_out_ee_bits(hw, 0, 4); + + /* Prepare the EEPROM */ + e1000_standby_eeprom(hw); + + /* Send the Write command (3-bit opcode + addr) */ + e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE, 3); + if(large_eeprom) + /* If we have a 256 word EEPROM, there are 8 address bits */ + e1000_shift_out_ee_bits(hw, offset, 8); + else + /* If we have a 64 word EEPROM, there are 6 address bits */ + e1000_shift_out_ee_bits(hw, offset, 6); + + /* Send the data */ + e1000_shift_out_ee_bits(hw, data, 16); + + /* Toggle the CS line. This in effect tells to EEPROM to actually execute + * the command in question. + */ + e1000_standby_eeprom(hw); + + /* Now read DO repeatedly until is high (equal to '1'). The EEEPROM will + * signal that the command has been completed by raising the DO signal. + * If DO does not go high in 10 milliseconds, then error out. + */ + for(i = 0; i < 200; i++) { + eecd = E1000_READ_REG(hw, EECD); + if(eecd & E1000_EECD_DO) break; + usec_delay(50); + } + if(i == 200) { + DEBUGOUT("EEPROM Write did not complete\n"); + status = -E1000_ERR_EEPROM; + } + + /* Recover from write */ + e1000_standby_eeprom(hw); + + /* Send the 9-bit (or 11-bit on large EEPROM) EWDS (write disable) command + * to the EEPROM (5-bit opcode plus 4/6-bit dummy). This takes the EEPROM + * out of write/erase mode. + */ + e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE, 5); + if(large_eeprom) + e1000_shift_out_ee_bits(hw, 0, 6); + else + e1000_shift_out_ee_bits(hw, 0, 4); + + /* Done with writing */ + e1000_cleanup_eeprom(hw); + + /* Stop requesting EEPROM access */ + if(hw->mac_type > e1000_82544) { + eecd = E1000_READ_REG(hw, EECD); + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + } + + return status; +} + +/****************************************************************************** * Reads the adapter's part number from the EEPROM * * hw - Struct containing variables accessed by shared code @@ -3334,4 +3534,41 @@ e1000_get_bus_info(struct e1000_hw *hw) hw->bus_width = (status & E1000_STATUS_BUS64) ? e1000_bus_width_64 : e1000_bus_width_32; } +/****************************************************************************** + * Reads a value from one of the devices registers using port I/O (as opposed + * memory mapped I/O). Only 82544 and newer devices support port I/O. + * + * hw - Struct containing variables accessed by shared code + * offset - offset to read from + *****************************************************************************/ +uint32_t +e1000_read_reg_io(struct e1000_hw *hw, + uint32_t offset) +{ + uint32_t io_addr = hw->io_base; + uint32_t io_data = hw->io_base + 4; + + e1000_io_write(hw, io_addr, offset); + return e1000_io_read(hw, io_data); +} + +/****************************************************************************** + * Writes a value to one of the devices registers using port I/O (as opposed to + * memory mapped I/O). Only 82544 and newer devices support port I/O. + * + * hw - Struct containing variables accessed by shared code + * offset - offset to write to + * value - value to write + *****************************************************************************/ +void +e1000_write_reg_io(struct e1000_hw *hw, + uint32_t offset, + uint32_t value) +{ + uint32_t io_addr = hw->io_base; + uint32_t io_data = hw->io_base + 4; + + e1000_io_write(hw, io_addr, offset); + e1000_io_write(hw, io_data, value); +} diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index da9a5027d2c2..ea64c9f8c171 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -236,6 +236,8 @@ int32_t e1000_validate_mdi_setting(struct e1000_hw *hw); /* EEPROM Functions */ int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t *data); int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw); +int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw); +int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t data); int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num); int32_t e1000_read_mac_addr(struct e1000_hw * hw); @@ -262,8 +264,19 @@ void e1000_reset_adaptive(struct e1000_hw *hw); void e1000_update_adaptive(struct e1000_hw *hw); void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr); void e1000_get_bus_info(struct e1000_hw *hw); +void e1000_pci_set_mwi(struct e1000_hw *hw); +void e1000_pci_clear_mwi(struct e1000_hw *hw); void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); +/* Port I/O is only supported on 82544 and newer */ +uint32_t e1000_io_read(struct e1000_hw *hw, uint32_t port); +uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset); +void e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value); +void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); +#define E1000_READ_REG_IO(a, reg) \ + e1000_read_reg_io((a), E1000_##reg) +#define E1000_WRITE_REG_IO(a, reg, val) \ + e1000_write_reg_io((a), E1000_##reg, val) /* PCI Device IDs */ #define E1000_DEV_ID_82542 0x1000 @@ -878,6 +891,7 @@ struct e1000_hw { e1000_bus_speed bus_speed; e1000_bus_width bus_width; e1000_bus_type bus_type; + uint32_t io_base; uint32_t phy_id; uint32_t phy_addr; uint32_t original_fc; @@ -1333,6 +1347,7 @@ struct e1000_hw { #define EEPROM_EWDS_OPCODE 0x10 /* EERPOM erast/write disable */ /* EEPROM Word Offsets */ +#define EEPROM_COMPAT 0x0003 #define EEPROM_ID_LED_SETTINGS 0x0004 #define EEPROM_INIT_CONTROL1_REG 0x000A #define EEPROM_INIT_CONTROL2_REG 0x000F @@ -1343,9 +1358,9 @@ struct e1000_hw { #define ID_LED_RESERVED_0000 0x0000 #define ID_LED_RESERVED_FFFF 0xFFFF #define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) + (ID_LED_OFF1_OFF2 << 8) | \ + (ID_LED_DEF1_DEF2 << 4) | \ + (ID_LED_DEF1_DEF2)) #define ID_LED_DEF1_DEF2 0x1 #define ID_LED_DEF1_ON2 0x2 #define ID_LED_DEF1_OFF2 0x3 @@ -1356,6 +1371,10 @@ struct e1000_hw { #define ID_LED_OFF1_ON2 0x8 #define ID_LED_OFF1_OFF2 0x9 +/* Mask bits for fields in Word 0x03 of the EEPROM */ +#define EEPROM_COMPAT_SERVER 0x0400 +#define EEPROM_COMPAT_CLIENT 0x0200 + /* Mask bits for fields in Word 0x0a of the EEPROM */ #define EEPROM_WORD0A_ILOS 0x0010 #define EEPROM_WORD0A_SWDPIO 0x01E0 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index bfbd58b61a6d..e8c7e46bd602 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -70,13 +70,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ - #define __E1000_MAIN__ #include "e1000.h" +/* Change Log + * + * 4.3.2 7/5/02 + * o Bug fix: perform controller reset using I/O rather than mmio because + * some chipsets try to perform a 64-bit write, but the controller ignores + * the upper 32-bit write once the reset is intiated by the lower 32-bit + * write, causing a master abort. + * o Bug fix: fixed jumbo frames sized from 1514 to 2048. + * o ASF support: disable ARP when driver is loaded or resumed; enable when + * driver is removed or suspended. + * o Bug fix: changed default setting for RxIntDelay to 0 for 82542/3/4 + * controllers to workaround h/w errata where controller will hang when + * RxIntDelay <> 0 under certian network conditions. + * o Clean up: removed unused and undocumented user-settable settings for + * PHY. + * o Bug fix: ethtool GEEPROM was using byte address rather than word + * addressing. + * o Feature: added support for ethtool SEEPROM. + * o Feature: added support for entropy pool. + * + * 4.2.17 5/30/02 + */ + char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -char e1000_driver_version[] = "4.2.17-k1"; +char e1000_driver_version[] = "4.3.2-k1"; char e1000_copyright[] = "Copyright (c) 1999-2002 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table @@ -156,7 +178,6 @@ static void e1000_set_multi(struct net_device *netdev); static void e1000_update_phy_info(unsigned long data); static void e1000_watchdog(unsigned long data); static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev); -static void e1000_tx_timeout(struct net_device *dev); static struct net_device_stats * e1000_get_stats(struct net_device *netdev); static int e1000_change_mtu(struct net_device *netdev, int new_mtu); static int e1000_set_mac(struct net_device *netdev, void *p); @@ -173,11 +194,11 @@ static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static inline void e1000_rx_checksum(struct e1000_adapter *adapter, struct e1000_rx_desc *rx_desc, struct sk_buff *skb); -#ifdef NETIF_F_HW_VLAN_TX +static void e1000_tx_timeout(struct net_device *dev); + static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); -#endif static int e1000_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); static int e1000_suspend(struct pci_dev *pdev, uint32_t state); @@ -260,7 +281,7 @@ e1000_up(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; - if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ, + if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name, netdev)) return -1; @@ -380,6 +401,15 @@ e1000_probe(struct pci_dev *pdev, if(!adapter->hw.hw_addr) goto err_ioremap; + for(i = BAR_1; i <= BAR_5; i++) { + if(pci_resource_len(pdev, i) == 0) + continue; + if(pci_resource_flags(pdev, i) & IORESOURCE_IO) { + adapter->hw.io_base = pci_resource_start(pdev, i); + break; + } + } + netdev->open = &e1000_open; netdev->stop = &e1000_close; netdev->hard_start_xmit = &e1000_xmit_frame; @@ -390,14 +420,13 @@ e1000_probe(struct pci_dev *pdev, netdev->do_ioctl = &e1000_ioctl; netdev->tx_timeout = &e1000_tx_timeout; netdev->watchdog_timeo = HZ; -#ifdef NETIF_F_HW_VLAN_TX netdev->vlan_rx_register = e1000_vlan_rx_register; netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid; -#endif netdev->irq = pdev->irq; - netdev->base_addr = mmio_start; + netdev->mem_start = mmio_start; + netdev->base_addr = adapter->hw.io_base; adapter->bd_number = cards_found; adapter->id_string = e1000_strings[ent->driver_data]; @@ -407,15 +436,11 @@ e1000_probe(struct pci_dev *pdev, e1000_sw_init(adapter); if(adapter->hw.mac_type >= e1000_82543) { -#ifdef NETIF_F_HW_VLAN_TX netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; -#else - netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM; -#endif } else { netdev->features = NETIF_F_SG; } @@ -509,7 +534,16 @@ e1000_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; - + uint32_t manc; + + if(adapter->hw.mac_type >= e1000_82540) { + manc = E1000_READ_REG(&adapter->hw, MANC); + if(manc & E1000_MANC_SMBUS_EN) { + manc |= E1000_MANC_ARP_EN; + E1000_WRITE_REG(&adapter->hw, MANC, manc); + } + } + unregister_netdev(netdev); e1000_phy_hw_reset(&adapter->hw); @@ -540,18 +574,12 @@ e1000_sw_init(struct e1000_adapter *adapter) /* PCI config space info */ - uint16_t *vendor = &hw->vendor_id; - uint16_t *device = &hw->device_id; - uint16_t *subvendor = &hw->subsystem_vendor_id; - uint16_t *subsystem = &hw->subsystem_id; - uint8_t *revision = &hw->revision_id; - - pci_read_config_word(pdev, PCI_VENDOR_ID, vendor); - pci_read_config_word(pdev, PCI_DEVICE_ID, device); - pci_read_config_byte(pdev, PCI_REVISION_ID, revision); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, subvendor); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, subsystem); - + pci_read_config_word(pdev, PCI_VENDOR_ID, &hw->vendor_id); + pci_read_config_word(pdev, PCI_DEVICE_ID, &hw->device_id); + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, + &hw->subsystem_vendor_id); + pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id); + pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); adapter->rx_buffer_len = E1000_RXBUFFER_2048; @@ -561,9 +589,9 @@ e1000_sw_init(struct e1000_adapter *adapter) /* identify the MAC */ - switch (*device) { + switch (hw->device_id) { case E1000_DEV_ID_82542: - switch (*revision) { + switch (hw->revision_id) { case E1000_82542_2_0_REV_ID: hw->mac_type = e1000_82542_rev2_0; break; @@ -597,7 +625,7 @@ e1000_sw_init(struct e1000_adapter *adapter) hw->mac_type = e1000_82546; break; default: - /* should never have loaded on this device */ + E1000_ERR("Should never have loaded on this device\n"); BUG(); } @@ -630,6 +658,13 @@ e1000_sw_init(struct e1000_adapter *adapter) hw->tbi_compatibility_en = TRUE; hw->adaptive_ifs = TRUE; + /* Copper options */ + + if(hw->media_type == e1000_media_type_copper) { + hw->mdix = AUTO_ALL_MODES; + hw->disable_polarity_correction = FALSE; + } + atomic_set(&adapter->irq_sem, 1); spin_lock_init(&adapter->stats_lock); } @@ -1089,20 +1124,16 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter) static void e1000_enter_82542_rst(struct e1000_adapter *adapter) { - struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; - uint16_t pci_command_word = adapter->hw.pci_cmd_word; uint32_t rctl; - if(pci_command_word & PCI_COMMAND_INVALIDATE) { - pci_command_word &= ~PCI_COMMAND_INVALIDATE; - pci_write_config_word(pdev, PCI_COMMAND, pci_command_word); - } + e1000_pci_clear_mwi(&adapter->hw); rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl |= E1000_RCTL_RST; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - msec_delay(5); + E1000_WRITE_FLUSH(&adapter->hw); + mdelay(5); if(netif_running(netdev)) e1000_clean_rx_ring(adapter); @@ -1111,18 +1142,17 @@ e1000_enter_82542_rst(struct e1000_adapter *adapter) static void e1000_leave_82542_rst(struct e1000_adapter *adapter) { - struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; - uint16_t pci_command_word = adapter->hw.pci_cmd_word; uint32_t rctl; rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl &= ~E1000_RCTL_RST; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - msec_delay(5); + E1000_WRITE_FLUSH(&adapter->hw); + mdelay(5); - if(pci_command_word & PCI_COMMAND_INVALIDATE) - pci_write_config_word(pdev, PCI_COMMAND, pci_command_word); + if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE) + e1000_pci_set_mwi(&adapter->hw); if(netif_running(netdev)) { e1000_configure_rx(adapter); @@ -1429,6 +1459,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) tx_ring->next_to_use = i; E1000_WRITE_REG(&adapter->hw, TDT, i); + E1000_WRITE_FLUSH(&adapter->hw); } #define TXD_USE_COUNT(S, X) (((S) / (X)) + (((S) % (X)) ? 1 : 0)) @@ -1458,12 +1489,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if(e1000_tx_csum(adapter, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; -#ifdef NETIF_F_HW_VLAN_TX if(adapter->vlgrp && vlan_tx_tag_present(skb)) { tx_flags |= E1000_TX_FLAGS_VLAN; tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); } -#endif count = e1000_tx_map(adapter, skb); @@ -1525,7 +1554,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; } - if(max_frame <= E1000_RXBUFFER_2048) { + if(max_frame <= MAXIMUM_ETHERNET_FRAME_SIZE) { adapter->rx_buffer_len = E1000_RXBUFFER_2048; } else if(adapter->hw.mac_type < e1000_82543) { @@ -1699,6 +1728,7 @@ e1000_irq_disable(struct e1000_adapter *adapter) { atomic_inc(&adapter->irq_sem); E1000_WRITE_REG(&adapter->hw, IMC, ~0); + E1000_WRITE_FLUSH(&adapter->hw); synchronize_irq(adapter->netdev->irq); } @@ -1710,8 +1740,10 @@ e1000_irq_disable(struct e1000_adapter *adapter) static inline void e1000_irq_enable(struct e1000_adapter *adapter) { - if(atomic_dec_and_test(&adapter->irq_sem)) + if(atomic_dec_and_test(&adapter->irq_sem)) { E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); + E1000_WRITE_FLUSH(&adapter->hw); + } } /** @@ -1779,8 +1811,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) tx_ring->buffer_info[i].skb = NULL; } - memset(tx_desc, 0, sizeof(struct e1000_tx_desc)); - mb(); + tx_desc->upper.data = 0; i = (i + 1) % tx_ring->count; tx_desc = E1000_TX_DESC(*tx_ring, i); @@ -1833,8 +1864,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) E1000_DBG("Receive packet consumed multiple buffers\n"); dev_kfree_skb_irq(skb); - memset(rx_desc, 0, sizeof(struct e1000_rx_desc)); - mb(); + rx_desc->status = 0; rx_ring->buffer_info[i].skb = NULL; i = (i + 1) % rx_ring->count; @@ -1862,8 +1892,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) } else { dev_kfree_skb_irq(skb); - memset(rx_desc, 0, sizeof(struct e1000_rx_desc)); - mb(); + rx_desc->status = 0; rx_ring->buffer_info[i].skb = NULL; i = (i + 1) % rx_ring->count; @@ -1880,20 +1909,15 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) e1000_rx_checksum(adapter, rx_desc, skb); skb->protocol = eth_type_trans(skb, netdev); -#ifdef NETIF_F_HW_VLAN_TX if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { vlan_hwaccel_rx(skb, adapter->vlgrp, (rx_desc->special & E1000_RXD_SPC_VLAN_MASK)); } else { netif_rx(skb); } -#else - netif_rx(skb); -#endif netdev->last_rx = jiffies; - memset(rx_desc, 0, sizeof(struct e1000_rx_desc)); - mb(); + rx_desc->status = 0; rx_ring->buffer_info[i].skb = NULL; i = (i + 1) % rx_ring->count; @@ -2018,6 +2042,22 @@ e1000_rx_checksum(struct e1000_adapter *adapter, } void +e1000_pci_set_mwi(struct e1000_hw *hw) +{ + struct e1000_adapter *adapter = hw->back; + + pci_set_mwi(adapter->pdev); +} + +void +e1000_pci_clear_mwi(struct e1000_hw *hw) +{ + struct e1000_adapter *adapter = hw->back; + + pci_clear_mwi(adapter->pdev); +} + +void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) { struct e1000_adapter *adapter = hw->back; @@ -2033,7 +2073,18 @@ e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) pci_write_config_word(adapter->pdev, reg, *value); } -#ifdef NETIF_F_HW_VLAN_TX +uint32_t +e1000_io_read(struct e1000_hw *hw, uint32_t port) +{ + return inl(port); +} + +void +e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value) +{ + outl(value, port); +} + static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) { @@ -2109,7 +2160,6 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) vfta &= ~(1 << (vid & 0x1F)); e1000_write_vfta(&adapter->hw, index, vfta); } -#endif static int e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) @@ -2133,7 +2183,7 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; - uint32_t ctrl, ctrl_ext, rctl; + uint32_t ctrl, ctrl_ext, rctl, manc; netif_device_detach(netdev); @@ -2171,7 +2221,15 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) } pci_save_state(pdev, adapter->pci_state); - pci_set_power_state(pdev, 3); + + if(adapter->hw.mac_type >= e1000_82540) { + manc = E1000_READ_REG(&adapter->hw, MANC); + if(manc & E1000_MANC_SMBUS_EN) { + manc |= E1000_MANC_ARP_EN; + E1000_WRITE_REG(&adapter->hw, MANC, manc); + } + } else + pci_set_power_state(pdev, 3); return 0; } @@ -2182,6 +2240,7 @@ e1000_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; + uint32_t manc; pci_set_power_state(pdev, 0); pci_restore_state(pdev, adapter->pci_state); @@ -2196,6 +2255,12 @@ e1000_resume(struct pci_dev *pdev) netif_device_attach(netdev); + if(adapter->hw.mac_type >= e1000_82540) { + manc = E1000_READ_REG(&adapter->hw, MANC); + manc &= ~(E1000_MANC_ARP_EN); + E1000_WRITE_REG(&adapter->hw, MANC, manc); + } + return 0; } #endif diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index e985682b7847..1f6d66b065dc 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -88,7 +88,8 @@ #define usec_delay(x) udelay(x) #ifndef msec_delay #define msec_delay(x) do { if(in_interrupt()) { \ - mdelay(x); \ + /* Don't mdelay in interrupt context! */ \ + BUG(); \ } else { \ set_current_state(TASK_UNINTERRUPTIBLE); \ schedule_timeout((x * HZ)/1000); \ @@ -140,4 +141,6 @@ typedef enum { readl((a)->hw_addr + E1000_##reg + ((offset) << 2)) : \ readl((a)->hw_addr + E1000_82542_##reg + ((offset) << 2))) +#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS); + #endif /* _E1000_OSDEP_H_ */ diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index 618515ae94f2..47127655cfcf 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -196,38 +196,11 @@ E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); * * Valid Range: 0-65535 * - * Default Value: 64/128 + * Default Value: 0/128 */ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); -/* MDI-X Support Enable/Disable - Applies only to Copper PHY - * - * Valid Range: 0, 3 - * - 0 - Auto in all modes - * - 1 - MDI - * - 2 - MDI-X - * - 3 - Auto in 1000 Base-T mode (MDI in 10 Base-T and 100 Base-T) - * - * Default Value: 0 (Auto) - */ - -E1000_PARAM(MdiX, "Set MDI/MDI-X Mode"); - -/* Automatic Correction of Reversed Cable Polarity Enable/Disable - * This setting applies only to Copper PHY - * - * Valid Range: 0, 1 - * - 0 - Disabled - * - 1 - Enabled - * - * Default Value: 1 (Enabled) - */ - -E1000_PARAM(DisablePolarityCorrection, - "Disable or enable Automatic Correction for Reversed Cable Polarity"); - - #define AUTONEG_ADV_DEFAULT 0x2F #define AUTONEG_ADV_MASK 0x2F #define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL @@ -242,16 +215,11 @@ E1000_PARAM(DisablePolarityCorrection, #define MIN_RXD 80 #define MAX_82544_RXD 4096 -#define DEFAULT_RDTR 64 +#define DEFAULT_RDTR 0 #define DEFAULT_RADV 128 #define MAX_RXDELAY 0xFFFF #define MIN_RXDELAY 0 -#define DEFAULT_MDIX 0 -#define MAX_MDIX 3 -#define MIN_MDIX 0 - - struct e1000_option { enum { enable_option, range_option, list_option } type; char *name; @@ -646,36 +614,6 @@ e1000_check_copper_options(struct e1000_adapter *adapter) BUG(); } - /* a few other copper only options */ - - { /* MDI/MDI-X */ - struct e1000_option opt = { - type: range_option, - name: "MDI/MDI-X", - err: "using default of " __MODULE_STRING(DEFAULT_MDIX), - def: DEFAULT_MDIX, - arg: { r: { min: MIN_MDIX, max: MAX_MDIX }} - }; - - int mdix = MdiX[bd]; - e1000_validate_option(&mdix, &opt); - adapter->hw.mdix = mdix; - } - { /* Automatic Correction for Reverse Cable Polarity */ - /* option is actually to disable polarity correction, - * so setting to OPTION_ENABLED turns the hardware feature off */ - struct e1000_option opt = { - type: enable_option, - name: "Disable Polarity Correction", - err: "defaulting to Disabled", - def: OPTION_DISABLED, - }; - - int dpc = DisablePolarityCorrection[bd]; - e1000_validate_option(&dpc, &opt); - adapter->hw.disable_polarity_correction = dpc; - } - /* Speed, AutoNeg and MDI/MDI-X must all play nice */ if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) { printk(KERN_INFO "Speed, AutoNeg and MDI-X specifications are " diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 485a0a319a98..19894d0db09f 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -25,6 +25,8 @@ Disabled FC and ER, to avoid lockups when when we get FCP interrupts. 2000 Jul 17 Goutham Rao <goutham.rao@intel.com> PCI DMA API fixes, adding pci_dma_sync_single calls where neccesary + 2000 Aug 31 David Mosberger <davidm@hpl.hp.com> + RX_ALIGN support: enables rx DMA without causing unaligned accesses. */ static const char *version = @@ -41,14 +43,18 @@ static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */ static int txdmacount = 128; static int rxdmacount /* = 0 */; +#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__) || defined(__mips__) || \ + defined(__arm__) + /* align rx buffers to 2 bytes so that IP header is aligned */ +# define RX_ALIGN +# define RxFD_ALIGNMENT __attribute__ ((aligned (2), packed)) +#else +# define RxFD_ALIGNMENT +#endif + /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method. Lower values use more memory, but are faster. */ -#if defined(__alpha__) || defined(__sparc__) || defined(__mips__) || \ - defined(__arm__) -static int rx_copybreak = 1518; -#else static int rx_copybreak = 200; -#endif /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ static int max_interrupt_work = 20; @@ -377,18 +383,18 @@ enum SCBPort_cmds { /* The Speedo3 Rx and Tx frame/buffer descriptors. */ struct descriptor { /* A generic descriptor. */ - s32 cmd_status; /* All command and status fields. */ + volatile s32 cmd_status; /* All command and status fields. */ u32 link; /* struct descriptor * */ unsigned char params[0]; }; /* The Speedo3 Rx and Tx buffer descriptors. */ struct RxFD { /* Receive frame descriptor. */ - s32 status; + volatile s32 status; u32 link; /* struct RxFD * */ u32 rx_buf_addr; /* void * */ u32 count; -}; +} RxFD_ALIGNMENT; /* Selected elements of the Tx/RxFD.status word. */ enum RxFD_bits { @@ -523,7 +529,12 @@ static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 }; static int eepro100_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); + static void eepro100_remove_one (struct pci_dev *pdev); +#ifdef CONFIG_PM +static int eepro100_suspend (struct pci_dev *pdev, u32 state); +static int eepro100_resume (struct pci_dev *pdev); +#endif static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len); static int mdio_read(long ioaddr, int phy_id, int location); @@ -1229,6 +1240,9 @@ speedo_init_rx_ring(struct net_device *dev) for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); +#ifdef RX_ALIGN + skb_reserve(skb, 2); /* Align IP on 16 byte boundary */ +#endif sp->rx_skbuff[i] = skb; if (skb == NULL) break; /* OK. Just initially short of Rx bufs. */ @@ -1620,6 +1634,9 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry) struct sk_buff *skb; /* Get a fresh skbuff to replace the consumed one. */ skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); +#ifdef RX_ALIGN + skb_reserve(skb, 2); /* Align IP on 16 byte boundary */ +#endif sp->rx_skbuff[entry] = skb; if (skb == NULL) { sp->rx_ringp[entry] = NULL; @@ -2303,7 +2320,9 @@ static struct pci_driver eepro100_driver = { name: "eepro100", id_table: eepro100_pci_tbl, probe: eepro100_init_one, +# if defined(MODULE) || defined(CONFIG_HOTPLUG) remove: __devexit_p(eepro100_remove_one), +# endif #ifdef CONFIG_PM suspend: eepro100_suspend, resume: eepro100_resume, |
