|
@@ -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);
|
|
|
}
|
|
|
|