summaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-04 11:47:58 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-04 11:47:58 -0700
commit6ba74014c1ab0e37af7de6f64b4eccbbae3cb9e7 (patch)
tree8f3892fc44f1e403675a6d7e88fda5c70e56ee4c /drivers/net/e1000e
parent5abd9ccced7a726c817dd6b5b96bc933859138d1 (diff)
parent3ff1c25927e3af61c6bf0e4ed959504058ae4565 (diff)
downloadop-kernel-dev-6ba74014c1ab0e37af7de6f64b4eccbbae3cb9e7.zip
op-kernel-dev-6ba74014c1ab0e37af7de6f64b4eccbbae3cb9e7.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1443 commits) phy/marvell: add 88ec048 support igb: Program MDICNFG register prior to PHY init e1000e: correct MAC-PHY interconnect register offset for 82579 hso: Add new product ID can: Add driver for esd CAN-USB/2 device l2tp: fix export of header file for userspace can-raw: Fix skb_orphan_try handling Revert "net: remove zap_completion_queue" net: cleanup inclusion phy/marvell: add 88e1121 interface mode support u32: negative offset fix net: Fix a typo from "dev" to "ndev" igb: Use irq_synchronize per vector when using MSI-X ixgbevf: fix null pointer dereference due to filter being set for VLAN 0 e1000e: Fix irq_synchronize in MSI-X case e1000e: register pm_qos request on hardware activation ip_fragment: fix subtracting PPPOE_SES_HLEN from mtu twice net: Add getsockopt support for TCP thin-streams cxgb4: update driver version cxgb4: add new PCI IDs ... Manually fix up conflicts in: - drivers/net/e1000e/netdev.c: due to pm_qos registration infrastructure changes - drivers/net/phy/marvell.c: conflict between adding 88ec048 support and cleaning up the IDs - drivers/net/wireless/ipw2x00/ipw2100.c: trivial ipw2100_pm_qos_req conflict (registration change vs marking it static)
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r--drivers/net/e1000e/82571.c2
-rw-r--r--drivers/net/e1000e/defines.h4
-rw-r--r--drivers/net/e1000e/e1000.h10
-rw-r--r--drivers/net/e1000e/es2lan.c2
-rw-r--r--drivers/net/e1000e/ethtool.c144
-rw-r--r--drivers/net/e1000e/hw.h17
-rw-r--r--drivers/net/e1000e/ich8lan.c456
-rw-r--r--drivers/net/e1000e/lib.c2
-rw-r--r--drivers/net/e1000e/netdev.c352
-rw-r--r--drivers/net/e1000e/param.c2
-rw-r--r--drivers/net/e1000e/phy.c5
11 files changed, 754 insertions, 242 deletions
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index f654db9..a4a0d2b 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 4dc02c7..307a72f4 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -359,6 +359,7 @@
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008
#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
+#define E1000_EXTCNF_CTRL_GATE_PHY_CFG 0x00000080
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16
#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000
@@ -714,6 +715,7 @@
#define BME1000_E_PHY_ID_R2 0x01410CB1
#define I82577_E_PHY_ID 0x01540050
#define I82578_E_PHY_ID 0x004DD040
+#define I82579_E_PHY_ID 0x01540090
/* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index c0b3db4..f9a31c8 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -164,6 +164,7 @@ enum e1000_boards {
board_ich9lan,
board_ich10lan,
board_pchlan,
+ board_pch2lan,
};
struct e1000_queue_stats {
@@ -347,6 +348,7 @@ struct e1000_adapter {
u32 test_icr;
u32 msg_enable;
+ unsigned int num_vectors;
struct msix_entry *msix_entries;
int int_mode;
u32 eiac_mask;
@@ -421,6 +423,8 @@ struct e1000_info {
#define FLAG2_HAS_PHY_WAKEUP (1 << 1)
#define FLAG2_IS_DISCARDING (1 << 2)
#define FLAG2_DISABLE_ASPM_L1 (1 << 3)
+#define FLAG2_HAS_PHY_STATS (1 << 4)
+#define FLAG2_HAS_EEE (1 << 5)
#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
@@ -458,7 +462,6 @@ extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
extern void e1000e_update_stats(struct e1000_adapter *adapter);
-extern bool e1000e_has_link(struct e1000_adapter *adapter);
extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
@@ -476,6 +479,7 @@ extern struct e1000_info e1000_ich8_info;
extern struct e1000_info e1000_ich9_info;
extern struct e1000_info e1000_ich10_info;
extern struct e1000_info e1000_pch_info;
+extern struct e1000_info e1000_pch2_info;
extern struct e1000_info e1000_es2_info;
extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
@@ -494,6 +498,8 @@ extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw);
extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
+extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
+extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw);
extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw);
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index 38d79a6..45aebb4 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 2c52121..6355a1b 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -118,7 +118,6 @@ static int e1000_get_settings(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- u32 status;
if (hw->phy.media_type == e1000_media_type_copper) {
@@ -156,22 +155,29 @@ static int e1000_get_settings(struct net_device *netdev,
ecmd->transceiver = XCVR_EXTERNAL;
}
- status = er32(STATUS);
- if (status & E1000_STATUS_LU) {
- if (status & E1000_STATUS_SPEED_1000)
- ecmd->speed = 1000;
- else if (status & E1000_STATUS_SPEED_100)
- ecmd->speed = 100;
- else
- ecmd->speed = 10;
+ ecmd->speed = -1;
+ ecmd->duplex = -1;
- if (status & E1000_STATUS_FD)
- ecmd->duplex = DUPLEX_FULL;
- else
- ecmd->duplex = DUPLEX_HALF;
+ if (netif_running(netdev)) {
+ if (netif_carrier_ok(netdev)) {
+ ecmd->speed = adapter->link_speed;
+ ecmd->duplex = adapter->link_duplex - 1;
+ }
} else {
- ecmd->speed = -1;
- ecmd->duplex = -1;
+ u32 status = er32(STATUS);
+ if (status & E1000_STATUS_LU) {
+ if (status & E1000_STATUS_SPEED_1000)
+ ecmd->speed = 1000;
+ else if (status & E1000_STATUS_SPEED_100)
+ ecmd->speed = 100;
+ else
+ ecmd->speed = 10;
+
+ if (status & E1000_STATUS_FD)
+ ecmd->duplex = DUPLEX_FULL;
+ else
+ ecmd->duplex = DUPLEX_HALF;
+ }
}
ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
@@ -179,7 +185,7 @@ static int e1000_get_settings(struct net_device *netdev,
/* MDI-X => 2; MDI =>1; Invalid =>0 */
if ((hw->phy.media_type == e1000_media_type_copper) &&
- !hw->mac.get_link_status)
+ netif_carrier_ok(netdev))
ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
ETH_TP_MDI;
else
@@ -191,19 +197,15 @@ static int e1000_get_settings(struct net_device *netdev,
static u32 e1000_get_link(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_mac_info *mac = &adapter->hw.mac;
+ struct e1000_hw *hw = &adapter->hw;
/*
- * If the link is not reported up to netdev, interrupts are disabled,
- * and so the physical link state may have changed since we last
- * looked. Set get_link_status to make sure that the true link
- * state is interrogated, rather than pulling a cached and possibly
- * stale link state from the driver.
+ * Avoid touching hardware registers when possible, otherwise
+ * link negotiation can get messed up when user-level scripts
+ * are rapidly polling the driver to see if link is up.
*/
- if (!netif_carrier_ok(netdev))
- mac->get_link_status = 1;
-
- return e1000e_has_link(adapter);
+ return netif_running(netdev) ? netif_carrier_ok(netdev) :
+ !!(er32(STATUS) & E1000_STATUS_LU);
}
static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
@@ -880,6 +882,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
switch (mac->type) {
case e1000_ich10lan:
case e1000_pchlan:
+ case e1000_pch2lan:
mask |= (1 << 18);
break;
default:
@@ -1263,33 +1266,36 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
hw->mac.autoneg = 0;
- /* Workaround: K1 must be disabled for stable 1Gbps operation */
- if (hw->mac.type == e1000_pchlan)
- e1000_configure_k1_ich8lan(hw, false);
-
- if (hw->phy.type == e1000_phy_m88) {
- /* Auto-MDI/MDIX Off */
- e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
- /* reset to update Auto-MDI/MDIX */
- e1e_wphy(hw, PHY_CONTROL, 0x9140);
- /* autoneg off */
- e1e_wphy(hw, PHY_CONTROL, 0x8140);
- } else if (hw->phy.type == e1000_phy_gg82563)
- e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC);
-
- ctrl_reg = er32(CTRL);
-
- switch (hw->phy.type) {
- case e1000_phy_ife:
+ if (hw->phy.type == e1000_phy_ife) {
/* force 100, set loopback */
e1e_wphy(hw, PHY_CONTROL, 0x6100);
/* Now set up the MAC to the same speed/duplex as the PHY. */
+ ctrl_reg = er32(CTRL);
ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
E1000_CTRL_SPD_100 |/* Force Speed to 100 */
E1000_CTRL_FD); /* Force Duplex to FULL */
+
+ ew32(CTRL, ctrl_reg);
+ udelay(500);
+
+ return 0;
+ }
+
+ /* Specific PHY configuration for loopback */
+ switch (hw->phy.type) {
+ case e1000_phy_m88:
+ /* Auto-MDI/MDIX Off */
+ e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
+ /* reset to update Auto-MDI/MDIX */
+ e1e_wphy(hw, PHY_CONTROL, 0x9140);
+ /* autoneg off */
+ e1e_wphy(hw, PHY_CONTROL, 0x8140);
+ break;
+ case e1000_phy_gg82563:
+ e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC);
break;
case e1000_phy_bm:
/* Set Default MAC Interface speed to 1GB */
@@ -1312,23 +1318,41 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
/* Set Early Link Enable */
e1e_rphy(hw, PHY_REG(769, 20), &phy_reg);
e1e_wphy(hw, PHY_REG(769, 20), phy_reg | 0x0400);
- /* fall through */
+ break;
+ case e1000_phy_82577:
+ case e1000_phy_82578:
+ /* Workaround: K1 must be disabled for stable 1Gbps operation */
+ e1000_configure_k1_ich8lan(hw, false);
+ break;
+ case e1000_phy_82579:
+ /* Disable PHY energy detect power down */
+ e1e_rphy(hw, PHY_REG(0, 21), &phy_reg);
+ e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~(1 << 3));
+ /* Disable full chip energy detect */
+ e1e_rphy(hw, PHY_REG(776, 18), &phy_reg);
+ e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1);
+ /* Enable loopback on the PHY */
+#define I82577_PHY_LBK_CTRL 19
+ e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001);
+ break;
default:
- /* force 1000, set loopback */
- e1e_wphy(hw, PHY_CONTROL, 0x4140);
- mdelay(250);
+ break;
+ }
- /* Now set up the MAC to the same speed/duplex as the PHY. */
- ctrl_reg = er32(CTRL);
- ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
- ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
- E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
- E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
- E1000_CTRL_FD); /* Force Duplex to FULL */
+ /* force 1000, set loopback */
+ e1e_wphy(hw, PHY_CONTROL, 0x4140);
+ mdelay(250);
- if (adapter->flags & FLAG_IS_ICH)
- ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */
- }
+ /* Now set up the MAC to the same speed/duplex as the PHY. */
+ ctrl_reg = er32(CTRL);
+ ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
+ ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
+ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+ E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
+ E1000_CTRL_FD); /* Force Duplex to FULL */
+
+ if (adapter->flags & FLAG_IS_ICH)
+ ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */
if (hw->phy.media_type == e1000_media_type_copper &&
hw->phy.type == e1000_phy_m88) {
@@ -1868,6 +1892,7 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
if ((hw->phy.type == e1000_phy_ife) ||
(hw->mac.type == e1000_pchlan) ||
+ (hw->mac.type == e1000_pch2lan) ||
(hw->mac.type == e1000_82583) ||
(hw->mac.type == e1000_82574)) {
INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task);
@@ -2026,7 +2051,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.get_coalesce = e1000_get_coalesce,
.set_coalesce = e1000_set_coalesce,
.get_flags = ethtool_op_get_flags,
- .set_flags = ethtool_op_set_flags,
};
void e1000e_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 5d1220d..66ed08f 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -217,7 +217,10 @@ enum e1e_registers {
E1000_SWSM = 0x05B50, /* SW Semaphore */
E1000_FWSM = 0x05B54, /* FW Semaphore */
E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */
- E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */
+ E1000_FFLT_DBG = 0x05F04, /* Debug Register */
+ E1000_PCH_RAICC_BASE = 0x05F50, /* Receive Address Initial CRC */
+#define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4))
+#define E1000_CRC_OFFSET E1000_PCH_RAICC_BASE
E1000_HICR = 0x08F00, /* Host Interface Control */
};
@@ -303,13 +306,14 @@ enum e1e_registers {
#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000
#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16
#define E1000_KMRNCTRLSTA_REN 0x00200000
+#define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */
#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
-#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E
-#define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400
+#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002
+#define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */
#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */
@@ -387,6 +391,8 @@ enum e1e_registers {
#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB
#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF
#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0
+#define E1000_DEV_ID_PCH2_LV_LM 0x1502
+#define E1000_DEV_ID_PCH2_LV_V 0x1503
#define E1000_REVISION_4 4
@@ -406,6 +412,7 @@ enum e1000_mac_type {
e1000_ich9lan,
e1000_ich10lan,
e1000_pchlan,
+ e1000_pch2lan,
};
enum e1000_media_type {
@@ -442,6 +449,7 @@ enum e1000_phy_type {
e1000_phy_bm,
e1000_phy_82578,
e1000_phy_82577,
+ e1000_phy_82579,
};
enum e1000_bus_width {
@@ -929,6 +937,7 @@ struct e1000_dev_spec_ich8lan {
bool kmrn_lock_loss_workaround_enabled;
struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
bool nvm_k1_enabled;
+ bool eee_disable;
};
struct e1000_hw {
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index b2507d9..63930d1 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -52,6 +52,8 @@
* 82577LC Gigabit Network Connection
* 82578DM Gigabit Network Connection
* 82578DC Gigabit Network Connection
+ * 82579LM Gigabit Network Connection
+ * 82579V Gigabit Network Connection
*/
#include "e1000.h"
@@ -126,6 +128,13 @@
#define HV_SMB_ADDR_PEC_EN 0x0200
#define HV_SMB_ADDR_VALID 0x0080
+/* PHY Power Management Control */
+#define HV_PM_CTRL PHY_REG(770, 17)
+
+/* PHY Low Power Idle Control */
+#define I82579_LPI_CTRL PHY_REG(772, 20)
+#define I82579_LPI_CTRL_ENABLE_MASK 0x6000
+
/* Strapping Option Register - RO */
#define E1000_STRAP 0x0000C
#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
@@ -226,6 +235,8 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);
static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
+static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
+static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
{
@@ -277,13 +288,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ /*
+ * The MAC-PHY interconnect may still be in SMBus mode
+ * after Sx->S0. If the manageability engine (ME) is
+ * disabled, then toggle the LANPHYPC Value bit to force
+ * the interconnect to PCIe mode.
+ */
if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
- /*
- * The MAC-PHY interconnect may still be in SMBus mode
- * after Sx->S0. Toggle the LANPHYPC Value bit to force
- * the interconnect to PCIe mode, but only if there is no
- * firmware present otherwise firmware will have done it.
- */
ctrl = er32(CTRL);
ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
@@ -324,6 +335,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
switch (phy->type) {
case e1000_phy_82577:
+ case e1000_phy_82579:
phy->ops.check_polarity = e1000_check_polarity_82577;
phy->ops.force_speed_duplex =
e1000_phy_force_speed_duplex_82577;
@@ -515,6 +527,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
case e1000_ich8lan:
case e1000_ich9lan:
case e1000_ich10lan:
+ /* check management mode */
+ mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan;
/* ID LED init */
mac->ops.id_led_init = e1000e_id_led_init;
/* setup LED */
@@ -526,6 +540,9 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
mac->ops.led_off = e1000_led_off_ich8lan;
break;
case e1000_pchlan:
+ case e1000_pch2lan:
+ /* check management mode */
+ mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
/* ID LED init */
mac->ops.id_led_init = e1000_id_led_init_pchlan;
/* setup LED */
@@ -544,10 +561,47 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
if (mac->type == e1000_ich8lan)
e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
+ /* Disable PHY configuration by hardware, config by software */
+ if (mac->type == e1000_pch2lan) {
+ u32 extcnf_ctrl = er32(EXTCNF_CTRL);
+
+ extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
+ }
+
return 0;
}
/**
+ * e1000_set_eee_pchlan - Enable/disable EEE support
+ * @hw: pointer to the HW structure
+ *
+ * Enable/disable EEE based on setting in dev_spec structure. The bits in
+ * the LPI Control register will remain set only if/when link is up.
+ **/
+static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
+{
+ s32 ret_val = 0;
+ u16 phy_reg;
+
+ if (hw->phy.type != e1000_phy_82579)
+ goto out;
+
+ ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
+ if (ret_val)
+ goto out;
+
+ if (hw->dev_spec.ich8lan.eee_disable)
+ phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK;
+ else
+ phy_reg |= I82579_LPI_CTRL_ENABLE_MASK;
+
+ ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
+out:
+ return ret_val;
+}
+
+/**
* e1000_check_for_copper_link_ich8lan - Check for link (Copper)
* @hw: pointer to the HW structure
*
@@ -604,6 +658,11 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
*/
e1000e_check_downshift(hw);
+ /* Enable/Disable EEE after link up */
+ ret_val = e1000_set_eee_pchlan(hw);
+ if (ret_val)
+ goto out;
+
/*
* If we are forcing speed/duplex, then we simply return since
* we have already determined whether we have link or not.
@@ -647,10 +706,19 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
if (rc)
return rc;
- if (hw->mac.type == e1000_pchlan)
- rc = e1000_init_phy_params_pchlan(hw);
- else
+ switch (hw->mac.type) {
+ case e1000_ich8lan:
+ case e1000_ich9lan:
+ case e1000_ich10lan:
rc = e1000_init_phy_params_ich8lan(hw);
+ break;
+ case e1000_pchlan:
+ case e1000_pch2lan:
+ rc = e1000_init_phy_params_pchlan(hw);
+ break;
+ default:
+ break;
+ }
if (rc)
return rc;
@@ -663,6 +731,10 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
(adapter->hw.phy.type == e1000_phy_igp_3))
adapter->flags |= FLAG_LSC_GIG_SPEED_DROP;
+ /* Disable EEE by default until IEEE802.3az spec is finalized */
+ if (adapter->flags2 & FLAG2_HAS_EEE)
+ adapter->hw.dev_spec.ich8lan.eee_disable = true;
+
return 0;
}
@@ -774,7 +846,7 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
* e1000_check_mng_mode_ich8lan - Checks management mode
* @hw: pointer to the HW structure
*
- * This checks if the adapter has manageability enabled.
+ * This checks if the adapter has any manageability enabled.
* This is a function pointer entry point only called by read/write
* routines for the PHY and NVM parts.
**/
@@ -783,9 +855,26 @@ static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw)
u32 fwsm;
fwsm = er32(FWSM);
+ return (fwsm & E1000_ICH_FWSM_FW_VALID) &&
+ ((fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
+}
+
+/**
+ * e1000_check_mng_mode_pchlan - Checks management mode
+ * @hw: pointer to the HW structure
+ *
+ * This checks if the adapter has iAMT enabled.
+ * This is a function pointer entry point only called by read/write
+ * routines for the PHY and NVM parts.
+ **/
+static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw)
+{
+ u32 fwsm;
- return (fwsm & E1000_FWSM_MODE_MASK) ==
- (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
+ fwsm = er32(FWSM);
+ return (fwsm & E1000_ICH_FWSM_FW_VALID) &&
+ (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
}
/**
@@ -820,14 +909,6 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
s32 ret_val = 0;
u16 word_addr, reg_data, reg_addr, phy_page = 0;
- if (!(hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) &&
- !(hw->mac.type == e1000_pchlan))
- return ret_val;
-
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- return ret_val;
-
/*
* Initialize the PHY from the NVM on ICH platforms. This
* is needed due to an issue where the NVM configuration is
@@ -835,12 +916,27 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
* Therefore, after each PHY reset, we will load the
* configuration data out of the NVM manually.
*/
- if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
- (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) ||
- (hw->mac.type == e1000_pchlan))
+ switch (hw->mac.type) {
+ case e1000_ich8lan:
+ if (phy->type != e1000_phy_igp_3)
+ return ret_val;
+
+ if (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) {
+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
+ break;
+ }
+ /* Fall-thru */
+ case e1000_pchlan:
+ case e1000_pch2lan:
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
- else
- sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
+ break;
+ default:
+ return ret_val;
+ }
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
data = er32(FEXTNVM);
if (!(data & sw_cfg_mask))
@@ -851,8 +947,10 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
* extended configuration before SW configuration
*/
data = er32(EXTCNF_CTRL);
- if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
- goto out;
+ if (!(hw->mac.type == e1000_pch2lan)) {
+ if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+ goto out;
+ }
cnf_size = er32(EXTCNF_SIZE);
cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
@@ -864,7 +962,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
- (hw->mac.type == e1000_pchlan)) {
+ ((hw->mac.type == e1000_pchlan) ||
+ (hw->mac.type == e1000_pch2lan))) {
/*
* HW configures the SMBus address and LEDs when the
* OEM and LCD Write Enable bits are set in the NVM.
@@ -1071,16 +1170,18 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
u32 mac_reg;
u16 oem_reg;
- if (hw->mac.type != e1000_pchlan)
+ if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan))
return ret_val;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
- mac_reg = er32(EXTCNF_CTRL);
- if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
- goto out;
+ if (!(hw->mac.type == e1000_pch2lan)) {
+ mac_reg = er32(EXTCNF_CTRL);
+ if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
+ goto out;
+ }
mac_reg = er32(FEXTNVM);
if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
@@ -1221,6 +1322,243 @@ out:
}
/**
+ * e1000_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY
+ * @hw: pointer to the HW structure
+ **/
+void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
+{
+ u32 mac_reg;
+ u16 i;
+
+ /* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
+ for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
+ mac_reg = er32(RAL(i));
+ e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
+ e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
+ mac_reg = er32(RAH(i));
+ e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
+ e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000));
+ }
+}
+
+static u32 e1000_calc_rx_da_crc(u8 mac[])
+{
+ u32 poly = 0xEDB88320; /* Polynomial for 802.3 CRC calculation */
+ u32 i, j, mask, crc;
+
+ crc = 0xffffffff;
+ for (i = 0; i < 6; i++) {
+ crc = crc ^ mac[i];
+ for (j = 8; j > 0; j--) {
+ mask = (crc & 1) * (-1);
+ crc = (crc >> 1) ^ (poly & mask);
+ }
+ }
+ return ~crc;
+}
+
+/**
+ * e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation
+ * with 82579 PHY
+ * @hw: pointer to the HW structure
+ * @enable: flag to enable/disable workaround when enabling/disabling jumbos
+ **/
+s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
+{
+ s32 ret_val = 0;
+ u16 phy_reg, data;
+ u32 mac_reg;
+ u16 i;
+
+ if (hw->mac.type != e1000_pch2lan)
+ goto out;
+
+ /* disable Rx path while enabling/disabling workaround */
+ e1e_rphy(hw, PHY_REG(769, 20), &phy_reg);
+ ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg | (1 << 14));
+ if (ret_val)
+ goto out;
+
+ if (enable) {
+ /*
+ * Write Rx addresses (rar_entry_count for RAL/H, +4 for
+ * SHRAL/H) and initial CRC values to the MAC
+ */
+ for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
+ u8 mac_addr[ETH_ALEN] = {0};
+ u32 addr_high, addr_low;
+
+ addr_high = er32(RAH(i));
+ if (!(addr_high & E1000_RAH_AV))
+ continue;
+ addr_low = er32(RAL(i));
+ mac_addr[0] = (addr_low & 0xFF);
+ mac_addr[1] = ((addr_low >> 8) & 0xFF);
+ mac_addr[2] = ((addr_low >> 16) & 0xFF);
+ mac_addr[3] = ((addr_low >> 24) & 0xFF);
+ mac_addr[4] = (addr_high & 0xFF);
+ mac_addr[5] = ((addr_high >> 8) & 0xFF);
+
+ ew32(PCH_RAICC(i),
+ e1000_calc_rx_da_crc(mac_addr));
+ }
+
+ /* Write Rx addresses to the PHY */
+ e1000_copy_rx_addrs_to_phy_ich8lan(hw);
+
+ /* Enable jumbo frame workaround in the MAC */
+ mac_reg = er32(FFLT_DBG);
+ mac_reg &= ~(1 << 14);
+ mac_reg |= (7 << 15);
+ ew32(FFLT_DBG, mac_reg);
+
+ mac_reg = er32(RCTL);
+ mac_reg |= E1000_RCTL_SECRC;
+ ew32(RCTL, mac_reg);
+
+ ret_val = e1000e_read_kmrn_reg(hw,
+ E1000_KMRNCTRLSTA_CTRL_OFFSET,
+ &data);
+ if (ret_val)
+ goto out;
+ ret_val = e1000e_write_kmrn_reg(hw,
+ E1000_KMRNCTRLSTA_CTRL_OFFSET,
+ data | (1 << 0));
+ if (ret_val)
+ goto out;
+ ret_val = e1000e_read_kmrn_reg(hw,
+ E1000_KMRNCTRLSTA_HD_CTRL,
+ &data);
+ if (ret_val)
+ goto out;
+ data &= ~(0xF << 8);
+ data |= (0xB << 8);
+ ret_val = e1000e_write_kmrn_reg(hw,
+ E1000_KMRNCTRLSTA_HD_CTRL,
+ data);
+ if (ret_val)
+ goto out;
+
+ /* Enable jumbo frame workaround in the PHY */
+ e1e_rphy(hw, PHY_REG(769, 20), &data);
+ ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
+ if (ret_val)
+ goto out;
+ e1e_rphy(hw, PHY_REG(769, 23), &data);
+ data &= ~(0x7F << 5);
+ data |= (0x37 << 5);
+ ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
+ if (ret_val)
+ goto out;
+ e1e_rphy(hw, PHY_REG(769, 16), &data);
+ data &= ~(1 << 13);
+ data |= (1 << 12);
+ ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
+ if (ret_val)
+ goto out;
+ e1e_rphy(hw, PHY_REG(776, 20), &data);
+ data &= ~(0x3FF << 2);
+ data |= (0x1A << 2);
+ ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
+ if (ret_val)
+ goto out;
+ ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xFE00);
+ if (ret_val)
+ goto out;
+ e1e_rphy(hw, HV_PM_CTRL, &data);
+ ret_val = e1e_wphy(hw, HV_PM_CTRL, data | (1 << 10));
+ if (ret_val)
+ goto out;
+ } else {
+ /* Write MAC register values back to h/w defaults */
+ mac_reg = er32(FFLT_DBG);
+ mac_reg &= ~(0xF << 14);
+ ew32(FFLT_DBG, mac_reg);
+
+ mac_reg = er32(RCTL);
+ mac_reg &= ~E1000_RCTL_SECRC;
+ ew32(FFLT_DBG, mac_reg);
+
+ ret_val = e1000e_read_kmrn_reg(hw,
+ E1000_KMRNCTRLSTA_CTRL_OFFSET,
+ &data);
+ if (ret_val)
+ goto out;
+ ret_val = e1000e_write_kmrn_reg(hw,
+ E1000_KMRNCTRLSTA_CTRL_OFFSET,
+ data & ~(1 << 0));
+ if (ret_val)
+ goto out;
+ ret_val = e1000e_read_kmrn_reg(hw,
+ E1000_KMRNCTRLSTA_HD_CTRL,
+ &data);
+ if (ret_val)
+ goto out;
+ data &= ~(0xF << 8);
+ data |= (0xB << 8);
+ ret_val = e1000e_write_kmrn_reg(hw,
+ E1000_KMRNCTRLSTA_HD_CTRL,
+ data);
+ if (ret_val)
+ goto out;
+
+ /* Write PHY register values back to h/w defaults */
+ e1e_rphy(hw, PHY_REG(769, 20), &data);
+ ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
+ if (ret_val)
+ goto out;
+ e1e_rphy(hw, PHY_REG(769, 23), &data);
+ data &= ~(0x7F << 5);
+ ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
+ if (ret_val)
+ goto out;
+ e1e_rphy(hw, PHY_REG(769, 16), &data);
+ data &= ~(1 << 12);
+ data |= (1 << 13);
+ ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
+ if (ret_val)
+ goto out;
+ e1e_rphy(hw, PHY_REG(776, 20), &data);
+ data &= ~(0x3FF << 2);
+ data |= (0x8 << 2);
+ ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
+ if (ret_val)
+ goto out;
+ ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0x7E00);
+ if (ret_val)
+ goto out;
+ e1e_rphy(hw, HV_PM_CTRL, &data);
+ ret_val = e1e_wphy(hw, HV_PM_CTRL, data & ~(1 << 10));
+ if (ret_val)
+ goto out;
+ }
+
+ /* re-enable Rx path after enabling/disabling workaround */
+ ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14));
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be
+ * done after every PHY reset.
+ **/
+static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw)
+{
+ s32 ret_val = 0;
+
+ if (hw->mac.type != e1000_pch2lan)
+ goto out;
+
+ /* Set MDIO slow mode before any other MDIO access */
+ ret_val = e1000_set_mdio_slow_mode_hv(hw);
+
+out:
+ return ret_val;
+}
+
+/**
* e1000_lan_init_done_ich8lan - Check for PHY config completion
* @hw: pointer to the HW structure
*
@@ -1271,12 +1609,17 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
if (ret_val)
goto out;
break;
+ case e1000_pch2lan:
+ ret_val = e1000_lv_phy_workarounds_ich8lan(hw);
+ if (ret_val)
+ goto out;
+ break;
default:
break;
}
/* Dummy read to clear the phy wakeup bit after lcd reset */
- if (hw->mac.type == e1000_pchlan)
+ if (hw->mac.type >= e1000_pchlan)
e1e_rphy(hw, BM_WUC, &reg);
/* Configure the LCD with the extended configuration region in NVM */
@@ -2800,6 +3143,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
ew32(FCTTV, hw->fc.pause_time);
if ((hw->phy.type == e1000_phy_82578) ||
+ (hw->phy.type == e1000_phy_82579) ||
(hw->phy.type == e1000_phy_82577)) {
ew32(FCRTV_PCH, hw->fc.refresh_time);
@@ -2863,6 +3207,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
return ret_val;
break;
case e1000_phy_82577:
+ case e1000_phy_82579:
ret_val = e1000_copper_link_setup_82577(hw);
if (ret_val)
return ret_val;
@@ -3116,21 +3461,12 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
{
u32 phy_ctrl;
- switch (hw->mac.type) {
- case e1000_ich8lan:
- case e1000_ich9lan:
- case e1000_ich10lan:
- case e1000_pchlan:
- phy_ctrl = er32(PHY_CTRL);
- phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU |
- E1000_PHY_CTRL_GBE_DISABLE;
- ew32(PHY_CTRL, phy_ctrl);
+ phy_ctrl = er32(PHY_CTRL);
+ phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE;
+ ew32(PHY_CTRL, phy_ctrl);
- if (hw->mac.type == e1000_pchlan)
- e1000_phy_hw_reset_ich8lan(hw);
- default:
- break;
- }
+ if (hw->mac.type >= e1000_pchlan)
+ e1000_phy_hw_reset_ich8lan(hw);
}
/**
@@ -3370,6 +3706,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
/* Clear PHY statistics registers */
if ((hw->phy.type == e1000_phy_82578) ||
+ (hw->phy.type == e1000_phy_82579) ||
(hw->phy.type == e1000_phy_82577)) {
hw->phy.ops.read_reg(hw, HV_SCC_UPPER, &phy_data);
hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data);
@@ -3390,7 +3727,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
static struct e1000_mac_operations ich8_mac_ops = {
.id_led_init = e1000e_id_led_init,
- .check_mng_mode = e1000_check_mng_mode_ich8lan,
+ /* check_mng_mode dependent on mac type */
.check_for_link = e1000_check_for_copper_link_ich8lan,
/* cleanup_led dependent on mac type */
.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan,
@@ -3497,6 +3834,7 @@ struct e1000_info e1000_pch_info = {
| FLAG_HAS_JUMBO_FRAMES
| FLAG_DISABLE_FC_PAUSE_TIME /* errata */
| FLAG_APME_IN_WUC,
+ .flags2 = FLAG2_HAS_PHY_STATS,
.pba = 26,
.max_hw_frame_size = 4096,
.get_variants = e1000_get_variants_ich8lan,
@@ -3504,3 +3842,23 @@ struct e1000_info e1000_pch_info = {
.phy_ops = &ich8_phy_ops,
.nvm_ops = &ich8_nvm_ops,
};
+
+struct e1000_info e1000_pch2_info = {
+ .mac = e1000_pch2lan,
+ .flags = FLAG_IS_ICH
+ | FLAG_HAS_WOL
+ | FLAG_RX_CSUM_ENABLED
+ | FLAG_HAS_CTRLEXT_ON_LOAD
+ | FLAG_HAS_AMT
+ | FLAG_HAS_FLASH
+ | FLAG_HAS_JUMBO_FRAMES
+ | FLAG_APME_IN_WUC,
+ .flags2 = FLAG2_HAS_PHY_STATS
+ | FLAG2_HAS_EEE,
+ .pba = 18,
+ .max_hw_frame_size = DEFAULT_JUMBO,
+ .get_variants = e1000_get_variants_ich8lan,
+ .mac_ops = &ich8_mac_ops,
+ .phy_ops = &ich8_phy_ops,
+ .nvm_ops = &ich8_nvm_ops,
+};
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index a968e3a..df4a279 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 9f13b66..36d31a4 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -52,7 +52,9 @@
#include "e1000.h"
-#define DRV_VERSION "1.0.2-k4"
+#define DRV_EXTRAVERSION "-k2"
+
+#define DRV_VERSION "1.2.7" DRV_EXTRAVERSION
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
@@ -67,6 +69,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
[board_ich9lan] = &e1000_ich9_info,
[board_ich10lan] = &e1000_ich10_info,
[board_pchlan] = &e1000_pch_info,
+ [board_pch2lan] = &e1000_pch2_info,
};
struct e1000_reg_info {
@@ -221,10 +224,10 @@ static void e1000e_dump(struct e1000_adapter *adapter)
buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean];
printk(KERN_INFO " %5d %5X %5X %016llX %04X %3X %016llX\n",
0, tx_ring->next_to_use, tx_ring->next_to_clean,
- (u64)buffer_info->dma,
+ (unsigned long long)buffer_info->dma,
buffer_info->length,
buffer_info->next_to_watch,
- (u64)buffer_info->time_stamp);
+ (unsigned long long)buffer_info->time_stamp);
/* Print TX Rings */
if (!netif_msg_tx_done(adapter))
@@ -276,9 +279,11 @@ static void e1000e_dump(struct e1000_adapter *adapter)
"%04X %3X %016llX %p",
(!(le64_to_cpu(u0->b) & (1<<29)) ? 'l' :
((le64_to_cpu(u0->b) & (1<<20)) ? 'd' : 'c')), i,
- le64_to_cpu(u0->a), le64_to_cpu(u0->b),
- (u64)buffer_info->dma, buffer_info->length,
- buffer_info->next_to_watch, (u64)buffer_info->time_stamp,
+ (unsigned long long)le64_to_cpu(u0->a),
+ (unsigned long long)le64_to_cpu(u0->b),
+ (unsigned long long)buffer_info->dma,
+ buffer_info->length, buffer_info->next_to_watch,
+ (unsigned long long)buffer_info->time_stamp,
buffer_info->skb);
if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean)
printk(KERN_CONT " NTC/U\n");
@@ -353,19 +358,19 @@ rx_ring_summary:
printk(KERN_INFO "RWB[0x%03X] %016llX "
"%016llX %016llX %016llX "
"---------------- %p", i,
- le64_to_cpu(u1->a),
- le64_to_cpu(u1->b),
- le64_to_cpu(u1->c),
- le64_to_cpu(u1->d),
+ (unsigned long long)le64_to_cpu(u1->a),
+ (unsigned long long)le64_to_cpu(u1->b),
+ (unsigned long long)le64_to_cpu(u1->c),
+ (unsigned long long)le64_to_cpu(u1->d),
buffer_info->skb);
} else {
printk(KERN_INFO "R [0x%03X] %016llX "
"%016llX %016llX %016llX %016llX %p", i,
- le64_to_cpu(u1->a),
- le64_to_cpu(u1->b),
- le64_to_cpu(u1->c),
- le64_to_cpu(u1->d),
- (u64)buffer_info->dma,
+ (unsigned long long)le64_to_cpu(u1->a),
+ (unsigned long long)le64_to_cpu(u1->b),
+ (unsigned long long)le64_to_cpu(u1->c),
+ (unsigned long long)le64_to_cpu(u1->d),
+ (unsigned long long)buffer_info->dma,
buffer_info->skb);
if (netif_msg_pktdata(adapter))
@@ -402,9 +407,11 @@ rx_ring_summary:
buffer_info = &rx_ring->buffer_info[i];
u0 = (struct my_u0 *)rx_desc;
printk(KERN_INFO "Rl[0x%03X] %016llX %016llX "
- "%016llX %p",
- i, le64_to_cpu(u0->a), le64_to_cpu(u0->b),
- (u64)buffer_info->dma, buffer_info->skb);
+ "%016llX %p", i,
+ (unsigned long long)le64_to_cpu(u0->a),
+ (unsigned long long)le64_to_cpu(u0->b),
+ (unsigned long long)buffer_info->dma,
+ buffer_info->skb);
if (i == rx_ring->next_to_use)
printk(KERN_CONT " NTU\n");
else if (i == rx_ring->next_to_clean)
@@ -1778,25 +1785,25 @@ void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter)
void e1000e_set_interrupt_capability(struct e1000_adapter *adapter)
{
int err;
- int numvecs, i;
-
+ int i;
switch (adapter->int_mode) {
case E1000E_INT_MODE_MSIX:
if (adapter->flags & FLAG_HAS_MSIX) {
- numvecs = 3; /* RxQ0, TxQ0 and other */
- adapter->msix_entries = kcalloc(numvecs,
+ adapter->num_vectors = 3; /* RxQ0, TxQ0 and other */
+ adapter->msix_entries = kcalloc(adapter->num_vectors,
sizeof(struct msix_entry),
GFP_KERNEL);
if (adapter->msix_entries) {
- for (i = 0; i < numvecs; i++)
+ for (i = 0; i < adapter->num_vectors; i++)
adapter->msix_entries[i].entry = i;
err = pci_enable_msix(adapter->pdev,
adapter->msix_entries,
- numvecs);
- if (err == 0)
+ adapter->num_vectors);
+ if (err == 0) {
return;
+ }
}
/* MSI-X failed, so fall through and try MSI */
e_err("Failed to initialize MSI-X interrupts. "
@@ -1818,6 +1825,9 @@ void e1000e_set_interrupt_capability(struct e1000_adapter *adapter)
/* Don't do anything; this is the system default */
break;
}
+
+ /* store the number of vectors being used */
+ adapter->num_vectors = 1;
}
/**
@@ -1939,7 +1949,14 @@ static void e1000_irq_disable(struct e1000_adapter *adapter)
if (adapter->msix_entries)
ew32(EIAC_82574, 0);
e1e_flush();
- synchronize_irq(adapter->pdev->irq);
+
+ if (adapter->msix_entries) {
+ int i;
+ for (i = 0; i < adapter->num_vectors; i++)
+ synchronize_irq(adapter->msix_entries[i].vector);
+ } else {
+ synchronize_irq(adapter->pdev->irq);
+ }
}
/**
@@ -2723,6 +2740,16 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
e1e_wphy(hw, 22, phy_data);
}
+ /* Workaround Si errata on 82579 - configure jumbo frame flow */
+ if (hw->mac.type == e1000_pch2lan) {
+ s32 ret_val;
+
+ if (rctl & E1000_RCTL_LPE)
+ ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
+ else
+ ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
+ }
+
/* Setup buffer sizes */
rctl &= ~E1000_RCTL_SZ_4096;
rctl |= E1000_RCTL_BSEX;
@@ -2759,7 +2786,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
* per packet.
*/
pages = PAGE_USE_COUNT(adapter->netdev->mtu);
- if (!(adapter->flags & FLAG_IS_ICH) && (pages <= 3) &&
+ if (!(adapter->flags & FLAG_HAS_ERT) && (pages <= 3) &&
(PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE))
adapter->rx_ps_pages = pages;
else
@@ -3118,7 +3145,27 @@ void e1000e_reset(struct e1000_adapter *adapter)
* with ERT support assuming ERT set to E1000_ERT_2048), or
* - the full Rx FIFO size minus one full frame
*/
- if (hw->mac.type == e1000_pchlan) {
+ if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)
+ fc->pause_time = 0xFFFF;
+ else
+ fc->pause_time = E1000_FC_PAUSE_TIME;
+ fc->send_xon = 1;
+ fc->current_mode = fc->requested_mode;
+
+ switch (hw->mac.type) {
+ default:
+ if ((adapter->flags & FLAG_HAS_ERT) &&
+ (adapter->netdev->mtu > ETH_DATA_LEN))
+ hwm = min(((pba << 10) * 9 / 10),
+ ((pba << 10) - (E1000_ERT_2048 << 3)));
+ else
+ hwm = min(((pba << 10) * 9 / 10),
+ ((pba << 10) - adapter->max_frame_size));
+
+ fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */
+ fc->low_water = fc->high_water - 8;
+ break;
+ case e1000_pchlan:
/*
* Workaround PCH LOM adapter hangs with certain network
* loads. If hangs persist, try disabling Tx flow control.
@@ -3131,26 +3178,15 @@ void e1000e_reset(struct e1000_adapter *adapter)
fc->low_water = 0x3000;
}
fc->refresh_time = 0x1000;
- } else {
- if ((adapter->flags & FLAG_HAS_ERT) &&
- (adapter->netdev->mtu > ETH_DATA_LEN))
- hwm = min(((pba << 10) * 9 / 10),
- ((pba << 10) - (E1000_ERT_2048 << 3)));
- else
- hwm = min(((pba << 10) * 9 / 10),
- ((pba << 10) - adapter->max_frame_size));
-
- fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */
- fc->low_water = fc->high_water - 8;
+ break;
+ case e1000_pch2lan:
+ fc->high_water = 0x05C20;
+ fc->low_water = 0x05048;
+ fc->pause_time = 0x0650;
+ fc->refresh_time = 0x0400;
+ break;
}
- if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)
- fc->pause_time = 0xFFFF;
- else
- fc->pause_time = E1000_FC_PAUSE_TIME;
- fc->send_xon = 1;
- fc->current_mode = fc->requested_mode;
-
/* Allow time for pending master requests to run */
mac->ops.reset_hw(hw);
@@ -3162,8 +3198,6 @@ void e1000e_reset(struct e1000_adapter *adapter)
e1000_get_hw_control(adapter);
ew32(WUC, 0);
- if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP)
- e1e_wphy(&adapter->hw, BM_WUC, 0);
if (mac->ops.init_hw(hw))
e_err("Hardware Error\n");
@@ -3194,12 +3228,6 @@ int e1000e_up(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
- /* DMA latency requirement to workaround early-receive/jumbo issue */
- if (adapter->flags & FLAG_HAS_ERT)
- pm_qos_add_request(&adapter->netdev->pm_qos_req,
- PM_QOS_CPU_DMA_LATENCY,
- PM_QOS_DEFAULT_VALUE);
-
/* hardware has been reset, we need to reload some things */
e1000_configure(adapter);
@@ -3263,9 +3291,6 @@ void e1000e_down(struct e1000_adapter *adapter)
e1000_clean_tx_ring(adapter);
e1000_clean_rx_ring(adapter);
- if (adapter->flags & FLAG_HAS_ERT)
- pm_qos_remove_request(&adapter->netdev->pm_qos_req);
-
/*
* TODO: for power management, we could drop the link and
* pci_disable_device here.
@@ -3416,13 +3441,18 @@ static int e1000_test_msi(struct e1000_adapter *adapter)
/* disable SERR in case the MSI write causes a master abort */
pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
- pci_write_config_word(adapter->pdev, PCI_COMMAND,
- pci_cmd & ~PCI_COMMAND_SERR);
+ if (pci_cmd & PCI_COMMAND_SERR)
+ pci_write_config_word(adapter->pdev, PCI_COMMAND,
+ pci_cmd & ~PCI_COMMAND_SERR);
err = e1000_test_msi_interrupt(adapter);
- /* restore previous setting of command word */
- pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
+ /* re-enable SERR */
+ if (pci_cmd & PCI_COMMAND_SERR) {
+ pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd |= PCI_COMMAND_SERR;
+ pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
+ }
/* success ! */
if (!err)
@@ -3495,6 +3525,12 @@ static int e1000_open(struct net_device *netdev)
E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
e1000_update_mng_vlan(adapter);
+ /* DMA latency requirement to workaround early-receive/jumbo issue */
+ if (adapter->flags & FLAG_HAS_ERT)
+ pm_qos_add_request(&adapter->netdev->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
+
/*
* before we allocate an interrupt, we must be ready to handle it.
* Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
@@ -3599,6 +3635,9 @@ static int e1000_close(struct net_device *netdev)
if (adapter->flags & FLAG_HAS_AMT)
e1000_release_hw_control(adapter);
+ if (adapter->flags & FLAG_HAS_ERT)
+ pm_qos_remove_request(&adapter->netdev->pm_qos_req);
+
pm_runtime_put_sync(&pdev->dev);
return 0;
@@ -3669,6 +3708,110 @@ static void e1000_update_phy_info(unsigned long data)
}
/**
+ * e1000e_update_phy_stats - Update the PHY statistics counters
+ * @adapter: board private structure
+ **/
+static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ s32 ret_val;
+ u16 phy_data;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return;
+
+ hw->phy.addr = 1;
+
+#define HV_PHY_STATS_PAGE 778
+ /*
+ * A page set is expensive so check if already on desired page.
+ * If not, set to the page with the PHY status registers.
+ */
+ ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
+ &phy_data);
+ if (ret_val)
+ goto release;
+ if (phy_data != (HV_PHY_STATS_PAGE << IGP_PAGE_SHIFT)) {
+ ret_val = e1000e_write_phy_reg_mdic(hw,
+ IGP01E1000_PHY_PAGE_SELECT,
+ (HV_PHY_STATS_PAGE <<
+ IGP_PAGE_SHIFT));
+ if (ret_val)
+ goto release;
+ }
+
+ /* Read/clear the upper 16-bit registers and read/accumulate lower */
+
+ /* Single Collision Count */
+ e1000e_read_phy_reg_mdic(hw, HV_SCC_UPPER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ ret_val = e1000e_read_phy_reg_mdic(hw,
+ HV_SCC_LOWER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ if (!ret_val)
+ adapter->stats.scc += phy_data;
+
+ /* Excessive Collision Count */
+ e1000e_read_phy_reg_mdic(hw, HV_ECOL_UPPER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ ret_val = e1000e_read_phy_reg_mdic(hw,
+ HV_ECOL_LOWER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ if (!ret_val)
+ adapter->stats.ecol += phy_data;
+
+ /* Multiple Collision Count */
+ e1000e_read_phy_reg_mdic(hw, HV_MCC_UPPER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ ret_val = e1000e_read_phy_reg_mdic(hw,
+ HV_MCC_LOWER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ if (!ret_val)
+ adapter->stats.mcc += phy_data;
+
+ /* Late Collision Count */
+ e1000e_read_phy_reg_mdic(hw, HV_LATECOL_UPPER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ ret_val = e1000e_read_phy_reg_mdic(hw,
+ HV_LATECOL_LOWER &
+ MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ if (!ret_val)
+ adapter->stats.latecol += phy_data;
+
+ /* Collision Count - also used for adaptive IFS */
+ e1000e_read_phy_reg_mdic(hw, HV_COLC_UPPER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ ret_val = e1000e_read_phy_reg_mdic(hw,
+ HV_COLC_LOWER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ if (!ret_val)
+ hw->mac.collision_delta = phy_data;
+
+ /* Defer Count */
+ e1000e_read_phy_reg_mdic(hw, HV_DC_UPPER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ ret_val = e1000e_read_phy_reg_mdic(hw,
+ HV_DC_LOWER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ if (!ret_val)
+ adapter->stats.dc += phy_data;
+
+ /* Transmit with no CRS */
+ e1000e_read_phy_reg_mdic(hw, HV_TNCRS_UPPER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ ret_val = e1000e_read_phy_reg_mdic(hw,
+ HV_TNCRS_LOWER & MAX_PHY_REG_ADDRESS,
+ &phy_data);
+ if (!ret_val)
+ adapter->stats.tncrs += phy_data;
+
+release:
+ hw->phy.ops.release(hw);
+}
+
+/**
* e1000e_update_stats - Update the board statistics counters
* @adapter: board private structure
**/
@@ -3677,7 +3820,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
- u16 phy_data;
/*
* Prevent stats update while adapter is being reset, or if the pci
@@ -3697,34 +3839,27 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
adapter->stats.roc += er32(ROC);
adapter->stats.mpc += er32(MPC);
- if ((hw->phy.type == e1000_phy_82578) ||
- (hw->phy.type == e1000_phy_82577)) {
- e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
- if (!e1e_rphy(hw, HV_SCC_LOWER, &phy_data))
- adapter->stats.scc += phy_data;
-
- e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
- if (!e1e_rphy(hw, HV_ECOL_LOWER, &phy_data))
- adapter->stats.ecol += phy_data;
-
- e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
- if (!e1e_rphy(hw, HV_MCC_LOWER, &phy_data))
- adapter->stats.mcc += phy_data;
-
- e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
- if (!e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data))
- adapter->stats.latecol += phy_data;
-
- e1e_rphy(hw, HV_DC_UPPER, &phy_data);
- if (!e1e_rphy(hw, HV_DC_LOWER, &phy_data))
- adapter->stats.dc += phy_data;
- } else {
- adapter->stats.scc += er32(SCC);
- adapter->stats.ecol += er32(ECOL);
- adapter->stats.mcc += er32(MCC);
- adapter->stats.latecol += er32(LATECOL);
- adapter->stats.dc += er32(DC);
+
+ /* Half-duplex statistics */
+ if (adapter->link_duplex == HALF_DUPLEX) {
+ if (adapter->flags2 & FLAG2_HAS_PHY_STATS) {
+ e1000e_update_phy_stats(adapter);
+ } else {
+ adapter->stats.scc += er32(SCC);
+ adapter->stats.ecol += er32(ECOL);
+ adapter->stats.mcc += er32(MCC);
+ adapter->stats.latecol += er32(LATECOL);
+ adapter->stats.dc += er32(DC);
+
+ hw->mac.collision_delta = er32(COLC);
+
+ if ((hw->mac.type != e1000_82574) &&
+ (hw->mac.type != e1000_82583))
+ adapter->stats.tncrs += er32(TNCRS);
+ }
+ adapter->stats.colc += hw->mac.collision_delta;
}
+
adapter->stats.xonrxc += er32(XONRXC);
adapter->stats.xontxc += er32(XONTXC);
adapter->stats.xoffrxc += er32(XOFFRXC);
@@ -3742,28 +3877,9 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
hw->mac.tx_packet_delta = er32(TPT);
adapter->stats.tpt += hw->mac.tx_packet_delta;
- if ((hw->phy.type == e1000_phy_82578) ||
- (hw->phy.type == e1000_phy_82577)) {
- e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
- if (!e1e_rphy(hw, HV_COLC_LOWER, &phy_data))
- hw->mac.collision_delta = phy_data;
- } else {
- hw->mac.collision_delta = er32(COLC);
- }
- adapter->stats.colc += hw->mac.collision_delta;
adapter->stats.algnerrc += er32(ALGNERRC);
adapter->stats.rxerrc += er32(RXERRC);
- if ((hw->phy.type == e1000_phy_82578) ||
- (hw->phy.type == e1000_phy_82577)) {
- e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
- if (!e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data))
- adapter->stats.tncrs += phy_data;
- } else {
- if ((hw->mac.type != e1000_82574) &&
- (hw->mac.type != e1000_82583))
- adapter->stats.tncrs += er32(TNCRS);
- }
adapter->stats.cexterr += er32(CEXTERR);
adapter->stats.tsctc += er32(TSCTC);
adapter->stats.tsctfc += er32(TSCTFC);
@@ -3862,7 +3978,7 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
}
-bool e1000e_has_link(struct e1000_adapter *adapter)
+static bool e1000e_has_link(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
bool link_active = 0;
@@ -4838,14 +4954,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
int retval = 0;
/* copy MAC RARs to PHY RARs */
- for (i = 0; i < adapter->hw.mac.rar_entry_count; i++) {
- mac_reg = er32(RAL(i));
- e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
- e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
- mac_reg = er32(RAH(i));
- e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
- e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0xFFFF));
- }
+ e1000_copy_rx_addrs_to_phy_ich8lan(hw);
/* copy MAC MTA to PHY MTA */
for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
@@ -5548,8 +5657,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (err)
goto err_sw_init;
- err = -EIO;
-
memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops));
memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops));
memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops));
@@ -5896,6 +6003,9 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan },
+
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
@@ -5932,7 +6042,7 @@ static int __init e1000_init_module(void)
int ret;
pr_info("Intel(R) PRO/1000 Network Driver - %s\n",
e1000e_driver_version);
- pr_info("Copyright (c) 1999 - 2009 Intel Corporation.\n");
+ pr_info("Copyright (c) 1999 - 2010 Intel Corporation.\n");
ret = pci_register_driver(&e1000_driver);
return ret;
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index a150e48..34aeec1 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index b4ac82d..3d3dc0c 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -2319,6 +2319,9 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
case I82577_E_PHY_ID:
phy_type = e1000_phy_82577;
break;
+ case I82579_E_PHY_ID:
+ phy_type = e1000_phy_82579;
+ break;
default:
phy_type = e1000_phy_unknown;
break;
OpenPOWER on IntegriCloud