igb: Add SMBI semaphore to I210/I211

It was previously thought that, since I210/I211 are single port devices,
they did not need the SMBI semaphore. This is not the case. Add support for
the SMBI semaphore.

Signed-off-by: Matthew Vick <matthew.vick@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
Matthew Vick 2013-03-22 07:34:20 +00:00 committed by Jeff Kirsher
parent 0ba96d3d91
commit d44e7a9a1f
3 changed files with 43 additions and 26 deletions

View file

@ -389,6 +389,9 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw)
dev_spec->eee_disable = false;
else
dev_spec->eee_disable = true;
/* Allow a single clear of the SW semaphore on I210 and newer */
if (mac->type >= e1000_i210)
dev_spec->clear_semaphore_once = true;
/* physical interface link setup */
mac->ops.setup_physical_interface =
(hw->phy.media_type == e1000_media_type_copper)

View file

@ -529,6 +529,7 @@ struct e1000_dev_spec_82575 {
bool sgmii_active;
bool global_device_reset;
bool eee_disable;
bool clear_semaphore_once;
};
struct e1000_hw {

View file

@ -44,10 +44,42 @@
static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
{
u32 swsm;
s32 ret_val = E1000_SUCCESS;
s32 timeout = hw->nvm.word_size + 1;
s32 i = 0;
/* Get the SW semaphore */
while (i < timeout) {
swsm = rd32(E1000_SWSM);
if (!(swsm & E1000_SWSM_SMBI))
break;
udelay(50);
i++;
}
if (i == timeout) {
/* In rare circumstances, the SW semaphore may already be held
* unintentionally. Clear the semaphore once before giving up.
*/
if (hw->dev_spec._82575.clear_semaphore_once) {
hw->dev_spec._82575.clear_semaphore_once = false;
igb_put_hw_semaphore(hw);
for (i = 0; i < timeout; i++) {
swsm = rd32(E1000_SWSM);
if (!(swsm & E1000_SWSM_SMBI))
break;
udelay(50);
}
}
/* If we do not have the semaphore here, we have to give up. */
if (i == timeout) {
hw_dbg("Driver can't access device - SMBI bit is set.\n");
return -E1000_ERR_NVM;
}
}
/* Get the FW semaphore. */
for (i = 0; i < timeout; i++) {
swsm = rd32(E1000_SWSM);
@ -64,12 +96,10 @@ static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
/* Release semaphores */
igb_put_hw_semaphore(hw);
hw_dbg("Driver can't access the NVM\n");
ret_val = -E1000_ERR_NVM;
goto out;
return -E1000_ERR_NVM;
}
out:
return ret_val;
return E1000_SUCCESS;
}
/**
@ -98,23 +128,6 @@ void igb_release_nvm_i210(struct e1000_hw *hw)
igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
}
/**
* igb_put_hw_semaphore_i210 - Release hardware semaphore
* @hw: pointer to the HW structure
*
* Release hardware semaphore used to access the PHY or NVM
**/
static void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
{
u32 swsm;
swsm = rd32(E1000_SWSM);
swsm &= ~E1000_SWSM_SWESMBI;
wr32(E1000_SWSM, swsm);
}
/**
* igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
* @hw: pointer to the HW structure
@ -138,11 +151,11 @@ s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
}
swfw_sync = rd32(E1000_SW_FW_SYNC);
if (!(swfw_sync & fwmask))
if (!(swfw_sync & (fwmask | swmask)))
break;
/* Firmware currently using resource (fwmask) */
igb_put_hw_semaphore_i210(hw);
igb_put_hw_semaphore(hw);
mdelay(5);
i++;
}
@ -156,7 +169,7 @@ s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
swfw_sync |= swmask;
wr32(E1000_SW_FW_SYNC, swfw_sync);
igb_put_hw_semaphore_i210(hw);
igb_put_hw_semaphore(hw);
out:
return ret_val;
}
@ -180,7 +193,7 @@ void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
swfw_sync &= ~mask;
wr32(E1000_SW_FW_SYNC, swfw_sync);
igb_put_hw_semaphore_i210(hw);
igb_put_hw_semaphore(hw);
}
/**