You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07: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:
committed by
Jeff Kirsher
parent
0ba96d3d91
commit
d44e7a9a1f
@@ -389,6 +389,9 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw)
|
|||||||
dev_spec->eee_disable = false;
|
dev_spec->eee_disable = false;
|
||||||
else
|
else
|
||||||
dev_spec->eee_disable = true;
|
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 */
|
/* physical interface link setup */
|
||||||
mac->ops.setup_physical_interface =
|
mac->ops.setup_physical_interface =
|
||||||
(hw->phy.media_type == e1000_media_type_copper)
|
(hw->phy.media_type == e1000_media_type_copper)
|
||||||
|
|||||||
@@ -529,6 +529,7 @@ struct e1000_dev_spec_82575 {
|
|||||||
bool sgmii_active;
|
bool sgmii_active;
|
||||||
bool global_device_reset;
|
bool global_device_reset;
|
||||||
bool eee_disable;
|
bool eee_disable;
|
||||||
|
bool clear_semaphore_once;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct e1000_hw {
|
struct e1000_hw {
|
||||||
|
|||||||
@@ -44,10 +44,42 @@
|
|||||||
static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
|
static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
|
||||||
{
|
{
|
||||||
u32 swsm;
|
u32 swsm;
|
||||||
s32 ret_val = E1000_SUCCESS;
|
|
||||||
s32 timeout = hw->nvm.word_size + 1;
|
s32 timeout = hw->nvm.word_size + 1;
|
||||||
s32 i = 0;
|
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. */
|
/* Get the FW semaphore. */
|
||||||
for (i = 0; i < timeout; i++) {
|
for (i = 0; i < timeout; i++) {
|
||||||
swsm = rd32(E1000_SWSM);
|
swsm = rd32(E1000_SWSM);
|
||||||
@@ -64,12 +96,10 @@ static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
|
|||||||
/* Release semaphores */
|
/* Release semaphores */
|
||||||
igb_put_hw_semaphore(hw);
|
igb_put_hw_semaphore(hw);
|
||||||
hw_dbg("Driver can't access the NVM\n");
|
hw_dbg("Driver can't access the NVM\n");
|
||||||
ret_val = -E1000_ERR_NVM;
|
return -E1000_ERR_NVM;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
return E1000_SUCCESS;
|
||||||
return ret_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,23 +128,6 @@ void igb_release_nvm_i210(struct e1000_hw *hw)
|
|||||||
igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
|
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
|
* igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
|
||||||
* @hw: pointer to the HW structure
|
* @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);
|
swfw_sync = rd32(E1000_SW_FW_SYNC);
|
||||||
if (!(swfw_sync & fwmask))
|
if (!(swfw_sync & (fwmask | swmask)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Firmware currently using resource (fwmask) */
|
/* Firmware currently using resource (fwmask) */
|
||||||
igb_put_hw_semaphore_i210(hw);
|
igb_put_hw_semaphore(hw);
|
||||||
mdelay(5);
|
mdelay(5);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -156,7 +169,7 @@ s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
|
|||||||
swfw_sync |= swmask;
|
swfw_sync |= swmask;
|
||||||
wr32(E1000_SW_FW_SYNC, swfw_sync);
|
wr32(E1000_SW_FW_SYNC, swfw_sync);
|
||||||
|
|
||||||
igb_put_hw_semaphore_i210(hw);
|
igb_put_hw_semaphore(hw);
|
||||||
out:
|
out:
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
@@ -180,7 +193,7 @@ void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
|
|||||||
swfw_sync &= ~mask;
|
swfw_sync &= ~mask;
|
||||||
wr32(E1000_SW_FW_SYNC, swfw_sync);
|
wr32(E1000_SW_FW_SYNC, swfw_sync);
|
||||||
|
|
||||||
igb_put_hw_semaphore_i210(hw);
|
igb_put_hw_semaphore(hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user