--- /dev/null
+From 23a2d1b233f535fc74f8dca66e488980b4db041b Mon Sep 17 00:00:00 2001
+From: Dave Graham <david.graham@intel.com>
+Date: Mon, 8 Jun 2009 14:28:17 +0000
+Subject: [PATCH] e1000e: Fixes possible phy corrupton on 82571 designs.
+References: bnc#495259
+
+Phy corruption has been observed on 2-port 82571 adapters, and is root-caused
+to lack of synchronization between the 2 driver instances, which conflict
+when attempting to access the phy via the single MDIC register.
+A semaphore exists for this purpose, and is now used on these designs. Because
+PXE &/or EFI boot code (which we cannot expect to be built with this fix) may
+leave the inter-instance semaphore in an invalid initial state when the driver
+first loads, this fix also includes a one-time (per driver load) fix-up of the
+semaphore initial state.
+
+Signed-off-by: dave graham <david.graham@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Brandon Philips <bphilips@suse.de>
+---
+ drivers/net/e1000e/82571.c | 86 +++++++++++++++++++++++++++++++++++++++----
+ drivers/net/e1000e/defines.h | 2 +
+ drivers/net/e1000e/hw.h | 2 +
+ 3 files changed, 83 insertions(+), 7 deletions(-)
+
+Index: linux-2.6.27-SLE11_BRANCH/drivers/net/e1000e/82571.c
+===================================================================
+--- linux-2.6.27-SLE11_BRANCH.orig/drivers/net/e1000e/82571.c
++++ linux-2.6.27-SLE11_BRANCH/drivers/net/e1000e/82571.c
+@@ -68,6 +68,7 @@ static s32 e1000_setup_link_82571(struct
+ static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
+ static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
+ static s32 e1000_led_on_82574(struct e1000_hw *hw);
++static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
+
+ /**
+ * e1000_init_phy_params_82571 - Init PHY func ptrs.
+@@ -206,6 +207,9 @@ static s32 e1000_init_mac_params_82571(s
+ struct e1000_hw *hw = &adapter->hw;
+ struct e1000_mac_info *mac = &hw->mac;
+ struct e1000_mac_operations *func = &mac->ops;
++ u32 swsm = 0;
++ u32 swsm2 = 0;
++ bool force_clear_smbi = false;
+
+ /* Set media type */
+ switch (adapter->pdev->device) {
+@@ -269,6 +273,50 @@ static s32 e1000_init_mac_params_82571(s
+ break;
+ }
+
++ /*
++ * Ensure that the inter-port SWSM.SMBI lock bit is clear before
++ * first NVM or PHY acess. This should be done for single-port
++ * devices, and for one port only on dual-port devices so that
++ * for those devices we can still use the SMBI lock to synchronize
++ * inter-port accesses to the PHY & NVM.
++ */
++ switch (hw->mac.type) {
++ case e1000_82571:
++ case e1000_82572:
++ swsm2 = er32(SWSM2);
++
++ if (!(swsm2 & E1000_SWSM2_LOCK)) {
++ /* Only do this for the first interface on this card */
++ ew32(SWSM2,
++ swsm2 | E1000_SWSM2_LOCK);
++ force_clear_smbi = true;
++ } else
++ force_clear_smbi = false;
++ break;
++ default:
++ force_clear_smbi = true;
++ break;
++ }
++
++ if (force_clear_smbi) {
++ /* Make sure SWSM.SMBI is clear */
++ swsm = er32(SWSM);
++ if (swsm & E1000_SWSM_SMBI) {
++ /* This bit should not be set on a first interface, and
++ * indicates that the bootagent or EFI code has
++ * improperly left this bit enabled
++ */
++ hw_dbg(hw, "Please update your 82571 Bootagent\n");
++ }
++ ew32(SWSM, swsm & ~E1000_SWSM_SMBI);
++ }
++
++ /*
++ * Initialze device specific counter of SMBI acquisition
++ * timeouts.
++ */
++ hw->dev_spec.e82571.smb_counter = 0;
++
+ return 0;
+ }
+
+@@ -402,11 +450,37 @@ static s32 e1000_get_phy_id_82571(struct
+ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
+ {
+ u32 swsm;
+- s32 timeout = hw->nvm.word_size + 1;
++ s32 sw_timeout = hw->nvm.word_size + 1;
++ s32 fw_timeout = hw->nvm.word_size + 1;
+ s32 i = 0;
+
++ /*
++ * If we have timedout 3 times on trying to acquire
++ * the inter-port SMBI semaphore, there is old code
++ * operating on the other port, and it is not
++ * releasing SMBI. Modify the number of times that
++ * we try for the semaphore to interwork with this
++ * older code.
++ */
++ if (hw->dev_spec.e82571.smb_counter > 2)
++ sw_timeout = 1;
++
++ /* Get the SW semaphore */
++ while (i < sw_timeout) {
++ swsm = er32(SWSM);
++ if (!(swsm & E1000_SWSM_SMBI))
++ break;
++
++ udelay(50);
++ i++;
++ }
++
++ if (i == sw_timeout) {
++ hw_dbg(hw, "Driver can't access device - SMBI bit is set.\n");
++ hw->dev_spec.e82571.smb_counter++;
++ }
+ /* Get the FW semaphore. */
+- for (i = 0; i < timeout; i++) {
++ for (i = 0; i < fw_timeout; i++) {
+ swsm = er32(SWSM);
+ ew32(SWSM, swsm | E1000_SWSM_SWESMBI);
+
+@@ -417,9 +491,9 @@ static s32 e1000_get_hw_semaphore_82571(
+ udelay(50);
+ }
+
+- if (i == timeout) {
++ if (i == fw_timeout) {
+ /* Release semaphores */
+- e1000e_put_hw_semaphore(hw);
++ e1000_put_hw_semaphore_82571(hw);
+ hw_dbg(hw, "Driver can't access the NVM\n");
+ return -E1000_ERR_NVM;
+ }
+@@ -438,9 +512,7 @@ static void e1000_put_hw_semaphore_82571
+ u32 swsm;
+
+ swsm = er32(SWSM);
+-
+- swsm &= ~E1000_SWSM_SWESMBI;
+-
++ swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
+ ew32(SWSM, swsm);
+ }
+
+Index: linux-2.6.27-SLE11_BRANCH/drivers/net/e1000e/defines.h
+===================================================================
+--- linux-2.6.27-SLE11_BRANCH.orig/drivers/net/e1000e/defines.h
++++ linux-2.6.27-SLE11_BRANCH/drivers/net/e1000e/defines.h
+@@ -359,6 +359,8 @@
+ #define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
+ #define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
+
++#define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */
++
+ /* Interrupt Cause Read */
+ #define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
+ #define E1000_ICR_LSC 0x00000004 /* Link Status Change */
+Index: linux-2.6.27-SLE11_BRANCH/drivers/net/e1000e/hw.h
+===================================================================
+--- linux-2.6.27-SLE11_BRANCH.orig/drivers/net/e1000e/hw.h
++++ linux-2.6.27-SLE11_BRANCH/drivers/net/e1000e/hw.h
+@@ -209,6 +209,7 @@ enum e1e_registers {
+ E1000_FACTPS = 0x05B30, /* Function Active and Power State to MNG */
+ E1000_SWSM = 0x05B50, /* SW Semaphore */
+ E1000_FWSM = 0x05B54, /* FW Semaphore */
++ E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */
+ E1000_HICR = 0x08F00, /* Host Interface Control */
+ };
+
+@@ -856,6 +857,7 @@ struct e1000_fc_info {
+ struct e1000_dev_spec_82571 {
+ bool laa_is_present;
+ bool alt_mac_addr_is_present;
++ u32 smb_counter;
+ };
+
+ struct e1000_shadow_ram {