summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-08-02 20:13:18 -0700
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-08-02 20:13:18 -0700
commit3334a8ca9896ca4d4ed5bd12a75aa139efcb3b56 (patch)
tree8e57e8d305a8b3ecba240c83f841bf75cef9e257
parent95c26f5af55e9efbc36084e7a3de07dd050f878b (diff)
parent67c5f644e47fe9576abbc036fb22735aa80a85f1 (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.txt26
-rw-r--r--drivers/net/8139cp.c62
-rw-r--r--drivers/net/e100/e100.h48
-rw-r--r--drivers/net/e100/e100_config.c85
-rw-r--r--drivers/net/e100/e100_config.h2
-rw-r--r--drivers/net/e100/e100_eeprom.c3
-rw-r--r--drivers/net/e100/e100_main.c550
-rw-r--r--drivers/net/e100/e100_phy.c47
-rw-r--r--drivers/net/e100/e100_phy.h21
-rw-r--r--drivers/net/e100/e100_proc.c413
-rw-r--r--drivers/net/e100/e100_test.c9
-rw-r--r--drivers/net/e100/e100_vendor.h13
-rw-r--r--drivers/net/e1000/e1000.h10
-rw-r--r--drivers/net/e1000/e1000_ethtool.c83
-rw-r--r--drivers/net/e1000/e1000_hw.c279
-rw-r--r--drivers/net/e1000/e1000_hw.h25
-rw-r--r--drivers/net/e1000/e1000_main.c187
-rw-r--r--drivers/net/e1000/e1000_osdep.h5
-rw-r--r--drivers/net/e1000/e1000_param.c66
-rw-r--r--drivers/net/eepro100.c35
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,