/** * igb_get_hw_semaphore_i210 - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM */ static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) { u32 swsm; 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); wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI) break; udelay(50); } if (i == timeout) { /* Release semaphores */ igb_put_hw_semaphore(hw); hw_dbg("Driver can't access the NVM\n"); return -E1000_ERR_NVM; } return 0; }
/** * igb_get_hw_semaphore_i210 - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM */ 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 FW semaphore. */ for (i = 0; i < timeout; i++) { swsm = rd32(E1000_SWSM); wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI) break; udelay(50); } if (i == timeout) { /* Release semaphores */ igb_put_hw_semaphore(hw); hw_dbg("Driver can't access the NVM\n"); ret_val = -E1000_ERR_NVM; goto out; } out: return ret_val; }
/** * igb_acquire_swfw_sync_82575 - Acquire SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Acquire the SW/FW semaphore to access the PHY or NVM. The mask * will also specify which port we're acquiring the lock for. **/ static s32 igb_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; u32 swmask = mask; u32 fwmask = mask << 16; s32 ret_val = 0; s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ while (i < timeout) { if (igb_get_hw_semaphore(hw)) { ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync = rd32(E1000_SW_FW_SYNC); if (!(swfw_sync & (fwmask | swmask))) break; /* * Firmware currently using resource (fwmask) * or other software thread using resource (swmask) */ igb_put_hw_semaphore(hw); mdelay(5); i++; } if (i == timeout) { hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync |= swmask; wr32(E1000_SW_FW_SYNC, swfw_sync); igb_put_hw_semaphore(hw); out: return ret_val; }
/** * igb_release_swfw_sync_82575 - Release SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Release the SW/FW semaphore used to access the PHY or NVM. The mask * will also specify which port we're releasing the lock for. **/ static void igb_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; while (igb_get_hw_semaphore(hw) != 0); /* Empty */ swfw_sync = rd32(E1000_SW_FW_SYNC); swfw_sync &= ~mask; wr32(E1000_SW_FW_SYNC, swfw_sync); igb_put_hw_semaphore(hw); }
static s32 igb_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; u32 swmask = mask; u32 fwmask = mask << 16; s32 ret_val = 0; s32 i = 0, timeout = 200; while (i < timeout) { if (igb_get_hw_semaphore(hw)) { ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync = rd32(E1000_SW_FW_SYNC); if (!(swfw_sync & (fwmask | swmask))) break; igb_put_hw_semaphore(hw); mdelay(5); i++; } if (i == timeout) { hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync |= swmask; wr32(E1000_SW_FW_SYNC, swfw_sync); igb_put_hw_semaphore(hw); out: return ret_val; }