mirror of
https://github.com/torvalds/linux.git
synced 2024-12-05 18:41:23 +00:00
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:
parent
0ba96d3d91
commit
d44e7a9a1f
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user