Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/e1000/e1000_mac.c
Show First 20 Lines • Show All 1,701 Lines • ▼ Show 20 Lines | s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw E1000_UNUSEDARG *hw, | ||||
*speed = SPEED_1000; | *speed = SPEED_1000; | ||||
*duplex = FULL_DUPLEX; | *duplex = FULL_DUPLEX; | ||||
return E1000_SUCCESS; | return E1000_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* e1000_get_hw_semaphore_generic - Acquire hardware semaphore | |||||
* @hw: pointer to the HW structure | |||||
* | |||||
* Acquire the HW semaphore to access the PHY or NVM | |||||
**/ | |||||
s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw) | |||||
{ | |||||
u32 swsm; | |||||
s32 timeout = hw->nvm.word_size + 1; | |||||
s32 i = 0; | |||||
DEBUGFUNC("e1000_get_hw_semaphore_generic"); | |||||
/* Get the SW semaphore */ | |||||
while (i < timeout) { | |||||
swsm = E1000_READ_REG(hw, E1000_SWSM); | |||||
if (!(swsm & E1000_SWSM_SMBI)) | |||||
break; | |||||
usec_delay(50); | |||||
i++; | |||||
} | |||||
if (i == timeout) { | |||||
DEBUGOUT("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 = E1000_READ_REG(hw, E1000_SWSM); | |||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); | |||||
/* Semaphore acquired if bit latched */ | |||||
if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) | |||||
break; | |||||
usec_delay(50); | |||||
} | |||||
if (i == timeout) { | |||||
/* Release semaphores */ | |||||
e1000_put_hw_semaphore_generic(hw); | |||||
DEBUGOUT("Driver can't access the NVM\n"); | |||||
return -E1000_ERR_NVM; | |||||
} | |||||
return E1000_SUCCESS; | |||||
} | |||||
/** | |||||
* e1000_put_hw_semaphore_generic - Release hardware semaphore | |||||
* @hw: pointer to the HW structure | |||||
* | |||||
* Release hardware semaphore used to access the PHY or NVM | |||||
**/ | |||||
void e1000_put_hw_semaphore_generic(struct e1000_hw *hw) | |||||
{ | |||||
u32 swsm; | |||||
DEBUGFUNC("e1000_put_hw_semaphore_generic"); | |||||
swsm = E1000_READ_REG(hw, E1000_SWSM); | |||||
swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); | |||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm); | |||||
} | |||||
/** | |||||
* e1000_get_auto_rd_done_generic - Check for auto read completion | * e1000_get_auto_rd_done_generic - Check for auto read completion | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* | * | ||||
* Check EEPROM for Auto Read done bit. | * Check EEPROM for Auto Read done bit. | ||||
**/ | **/ | ||||
s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw) | s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw) | ||||
{ | { | ||||
s32 i = 0; | s32 i = 0; | ||||
▲ Show 20 Lines • Show All 458 Lines • ▼ Show 20 Lines | s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, | ||||
} | } | ||||
if (!(regvalue & E1000_GEN_CTL_READY)) { | if (!(regvalue & E1000_GEN_CTL_READY)) { | ||||
DEBUGOUT1("Reg %08x did not indicate ready\n", reg); | DEBUGOUT1("Reg %08x did not indicate ready\n", reg); | ||||
return -E1000_ERR_PHY; | return -E1000_ERR_PHY; | ||||
} | } | ||||
return E1000_SUCCESS; | return E1000_SUCCESS; | ||||
} | } | ||||
/** | |||||
* e1000_get_hw_semaphore - Acquire hardware semaphore | |||||
* @hw: pointer to the HW structure | |||||
* | |||||
* Acquire the HW semaphore to access the PHY or NVM | |||||
**/ | |||||
s32 e1000_get_hw_semaphore(struct e1000_hw *hw) | |||||
{ | |||||
u32 swsm; | |||||
s32 timeout = hw->nvm.word_size + 1; | |||||
s32 i = 0; | |||||
DEBUGFUNC("e1000_get_hw_semaphore"); | |||||
#ifdef notyet | |||||
/* _82571 */ | |||||
/* 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._82571.smb_counter > 2) | |||||
sw_timeout = 1; | |||||
#endif | |||||
/* Get the SW semaphore */ | |||||
while (i < timeout) { | |||||
swsm = E1000_READ_REG(hw, E1000_SWSM); | |||||
if (!(swsm & E1000_SWSM_SMBI)) | |||||
break; | |||||
usec_delay(50); | |||||
i++; | |||||
} | |||||
if (i == timeout) { | |||||
#ifdef notyet | |||||
/* | |||||
* XXX This sounds more like a driver bug whereby we either | |||||
* recursed accidentally or missed clearing it previously | |||||
*/ | |||||
/* 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; | |||||
e1000_put_hw_semaphore_generic(hw); | |||||
for (i = 0; i < timeout; i++) { | |||||
swsm = E1000_READ_REG(hw, E1000_SWSM); | |||||
if (!(swsm & E1000_SWSM_SMBI)) | |||||
break; | |||||
usec_delay(50); | |||||
} | |||||
} | |||||
#endif | |||||
DEBUGOUT("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 = E1000_READ_REG(hw, E1000_SWSM); | |||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); | |||||
/* Semaphore acquired if bit latched */ | |||||
if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) | |||||
break; | |||||
usec_delay(50); | |||||
} | |||||
if (i == timeout) { | |||||
/* Release semaphores */ | |||||
e1000_put_hw_semaphore(hw); | |||||
DEBUGOUT("Driver can't access the NVM\n"); | |||||
return -E1000_ERR_NVM; | |||||
} | |||||
return E1000_SUCCESS; | |||||
} | |||||
/** | |||||
* e1000_put_hw_semaphore - Release hardware semaphore | |||||
* @hw: pointer to the HW structure | |||||
* | |||||
* Release hardware semaphore used to access the PHY or NVM | |||||
**/ | |||||
void e1000_put_hw_semaphore(struct e1000_hw *hw) | |||||
{ | |||||
u32 swsm; | |||||
DEBUGFUNC("e1000_put_hw_semaphore"); | |||||
swsm = E1000_READ_REG(hw, E1000_SWSM); | |||||
swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); | |||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm); | |||||
} | |||||
/** | |||||
* e1000_acquire_swfw_sync - 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. | |||||
**/ | |||||
s32 | |||||
e1000_acquire_swfw_sync(struct e1000_hw *hw, u16 mask) | |||||
{ | |||||
u32 swfw_sync; | |||||
u32 swmask = mask; | |||||
u32 fwmask = mask << 16; | |||||
s32 ret_val = E1000_SUCCESS; | |||||
s32 i = 0, timeout = 200; | |||||
DEBUGFUNC("e1000_acquire_swfw_sync"); | |||||
ASSERT_NO_LOCKS(); | |||||
while (i < timeout) { | |||||
if (e1000_get_hw_semaphore(hw)) { | |||||
ret_val = -E1000_ERR_SWFW_SYNC; | |||||
goto out; | |||||
} | |||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); | |||||
if (!(swfw_sync & (fwmask | swmask))) | |||||
break; | |||||
/* | |||||
* Firmware currently using resource (fwmask) | |||||
* or other software thread using resource (swmask) | |||||
*/ | |||||
e1000_put_hw_semaphore(hw); | |||||
msec_delay_irq(5); | |||||
i++; | |||||
} | |||||
if (i == timeout) { | |||||
DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); | |||||
ret_val = -E1000_ERR_SWFW_SYNC; | |||||
goto out; | |||||
} | |||||
swfw_sync |= swmask; | |||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); | |||||
e1000_put_hw_semaphore(hw); | |||||
out: | |||||
return ret_val; | |||||
} | |||||
/** | |||||
* e1000_release_swfw_sync - 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. | |||||
**/ | |||||
void | |||||
e1000_release_swfw_sync(struct e1000_hw *hw, u16 mask) | |||||
{ | |||||
u32 swfw_sync; | |||||
DEBUGFUNC("e1000_release_swfw_sync"); | |||||
while (e1000_get_hw_semaphore(hw) != E1000_SUCCESS) | |||||
; /* Empty */ | |||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); | |||||
swfw_sync &= ~mask; | |||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); | |||||
e1000_put_hw_semaphore(hw); | |||||
} | |||||