netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [net-next PATCH 1/3] e1000e: Fixes possible phy corrupton on 82571 designs.
@ 2009-06-09  0:28 Jeff Kirsher
  2009-06-09  0:28 ` [net-next PATCH 2/3] e1000e: Call e1000e_config_collision_dist() after TCTL has been set Jeff Kirsher
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jeff Kirsher @ 2009-06-09  0:28 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, dave graham, Jeff Kirsher

From: Dave Graham <david.graham@intel.com>

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>
---

 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(-)

diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index c4b3f4f..b53b40b 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -71,6 +71,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw);
 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.
@@ -212,6 +213,9 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
 	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) {
@@ -276,6 +280,50 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
 		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;
 }
 
@@ -413,11 +461,37 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
 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);
 
@@ -428,9 +502,9 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
 		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;
 	}
@@ -449,9 +523,7 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
 	u32 swsm;
 
 	swsm = er32(SWSM);
-
-	swsm &= ~E1000_SWSM_SWESMBI;
-
+	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
 	ew32(SWSM, swsm);
 }
 
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 674a47e..8890c97 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -376,6 +376,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 */
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index fce3f05..163c1c0 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -214,6 +214,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 */
 };
 
@@ -883,6 +884,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 {


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [net-next PATCH 2/3] e1000e: Call e1000e_config_collision_dist() after TCTL has been set
  2009-06-09  0:28 [net-next PATCH 1/3] e1000e: Fixes possible phy corrupton on 82571 designs Jeff Kirsher
@ 2009-06-09  0:28 ` Jeff Kirsher
  2009-06-09  0:28 ` [net-next PATCH 3/3] e1000e: Expose MDI-X status via ethtool change Jeff Kirsher
  2009-06-09 12:21 ` [net-next PATCH 1/3] e1000e: Fixes possible phy corrupton on 82571 designs David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Jeff Kirsher @ 2009-06-09  0:28 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Simon Horman, Jeff Kirsher

From: Simon Horman <horms@verge.net.au>

e1000e_config_collision_dist() sets tctl, but subsequently tctl is
overwritten.  It seems to me that as things stand the call to
e1000e_config_collision_dist() has no effect and should either be
removed or moved down a little bit.  This kernel patch takes the latter
option.

Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/netdev.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 9043f1b..677f604 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2256,8 +2256,6 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
 		ew32(TARC(1), tarc);
 	}
 
-	e1000e_config_collision_dist(hw);
-
 	/* Setup Transmit Descriptor Settings for eop descriptor */
 	adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS;
 
@@ -2270,6 +2268,8 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
 
 	ew32(TCTL, tctl);
 
+	e1000e_config_collision_dist(hw);
+
 	adapter->tx_queue_len = adapter->netdev->tx_queue_len;
 }
 


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [net-next PATCH 3/3] e1000e: Expose MDI-X status via ethtool change
  2009-06-09  0:28 [net-next PATCH 1/3] e1000e: Fixes possible phy corrupton on 82571 designs Jeff Kirsher
  2009-06-09  0:28 ` [net-next PATCH 2/3] e1000e: Call e1000e_config_collision_dist() after TCTL has been set Jeff Kirsher
@ 2009-06-09  0:28 ` Jeff Kirsher
  2009-06-09 12:21 ` [net-next PATCH 1/3] e1000e: Fixes possible phy corrupton on 82571 designs David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Jeff Kirsher @ 2009-06-09  0:28 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Chaitanya Lala, Arthur Jones, Jeff Kirsher

From: Chaitanya Lala <clala@riverbed.com>

Ethtool is a standard way of getting information about
ethernet interfaces.  We enhance ethtool kernel interface
& e1000e to make the MDI-X status readable via ethtool in
userspace.

Signed-off-by: Chaitanya Lala <clala@riverbed.com>
Signed-off-by: Arthur Jones <ajones@riverbed.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/ethtool.c |    9 +++++++++
 include/linux/ethtool.h      |    8 +++++++-
 2 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 3d64356..1bf4d2a 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -167,6 +167,15 @@ static int e1000_get_settings(struct net_device *netdev,
 
 	ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
 			 hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+
+	/* MDI-X => 2; MDI =>1; Invalid =>0 */
+	if ((hw->phy.media_type == e1000_media_type_copper) &&
+	    !hw->mac.get_link_status)
+		ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
+		                                      ETH_TP_MDI;
+	else
+		ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
+
 	return 0;
 }
 
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 380b042..9b660bd 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -30,7 +30,8 @@ struct ethtool_cmd {
 	__u32	maxtxpkt;	/* Tx pkts before generating tx int */
 	__u32	maxrxpkt;	/* Rx pkts before generating rx int */
 	__u16	speed_hi;
-	__u16	reserved2;
+	__u8	eth_tp_mdix;
+	__u8	reserved2;
 	__u32	lp_advertising;	/* Features the link partner advertises */
 	__u32	reserved[2];
 };
@@ -632,6 +633,11 @@ struct ethtool_ops {
 #define AUTONEG_DISABLE		0x00
 #define AUTONEG_ENABLE		0x01
 
+/* Mode MDI or MDI-X */
+#define ETH_TP_MDI_INVALID	0x00
+#define ETH_TP_MDI		0x01
+#define ETH_TP_MDI_X		0x02
+
 /* Wake-On-Lan options. */
 #define WAKE_PHY		(1 << 0)
 #define WAKE_UCAST		(1 << 1)


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [net-next PATCH 1/3] e1000e: Fixes possible phy corrupton on 82571 designs.
  2009-06-09  0:28 [net-next PATCH 1/3] e1000e: Fixes possible phy corrupton on 82571 designs Jeff Kirsher
  2009-06-09  0:28 ` [net-next PATCH 2/3] e1000e: Call e1000e_config_collision_dist() after TCTL has been set Jeff Kirsher
  2009-06-09  0:28 ` [net-next PATCH 3/3] e1000e: Expose MDI-X status via ethtool change Jeff Kirsher
@ 2009-06-09 12:21 ` David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2009-06-09 12:21 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, david.graham


All 3 patches applied.



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-06-09 12:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-09  0:28 [net-next PATCH 1/3] e1000e: Fixes possible phy corrupton on 82571 designs Jeff Kirsher
2009-06-09  0:28 ` [net-next PATCH 2/3] e1000e: Call e1000e_config_collision_dist() after TCTL has been set Jeff Kirsher
2009-06-09  0:28 ` [net-next PATCH 3/3] e1000e: Expose MDI-X status via ethtool change Jeff Kirsher
2009-06-09 12:21 ` [net-next PATCH 1/3] e1000e: Fixes possible phy corrupton on 82571 designs David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).