|
@@ -793,29 +793,31 @@ release:
|
|
|
* When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
|
|
|
* preventing further DMA write requests. Workaround the issue by disabling
|
|
|
* the de-assertion of the clock request when in 1Gpbs mode.
|
|
|
+ * Also, set appropriate Tx re-transmission timeouts for 10 and 100Half link
|
|
|
+ * speeds in order to avoid Tx hangs.
|
|
|
**/
|
|
|
static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
|
|
|
{
|
|
|
u32 fextnvm6 = er32(FEXTNVM6);
|
|
|
+ u32 status = er32(STATUS);
|
|
|
s32 ret_val = 0;
|
|
|
+ u16 reg;
|
|
|
|
|
|
- if (link && (er32(STATUS) & E1000_STATUS_SPEED_1000)) {
|
|
|
- u16 kmrn_reg;
|
|
|
-
|
|
|
+ if (link && (status & E1000_STATUS_SPEED_1000)) {
|
|
|
ret_val = hw->phy.ops.acquire(hw);
|
|
|
if (ret_val)
|
|
|
return ret_val;
|
|
|
|
|
|
ret_val =
|
|
|
e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
|
|
|
- &kmrn_reg);
|
|
|
+ ®);
|
|
|
if (ret_val)
|
|
|
goto release;
|
|
|
|
|
|
ret_val =
|
|
|
e1000e_write_kmrn_reg_locked(hw,
|
|
|
E1000_KMRNCTRLSTA_K1_CONFIG,
|
|
|
- kmrn_reg &
|
|
|
+ reg &
|
|
|
~E1000_KMRNCTRLSTA_K1_ENABLE);
|
|
|
if (ret_val)
|
|
|
goto release;
|
|
@@ -827,12 +829,45 @@ static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
|
|
|
ret_val =
|
|
|
e1000e_write_kmrn_reg_locked(hw,
|
|
|
E1000_KMRNCTRLSTA_K1_CONFIG,
|
|
|
- kmrn_reg);
|
|
|
+ reg);
|
|
|
release:
|
|
|
hw->phy.ops.release(hw);
|
|
|
} else {
|
|
|
/* clear FEXTNVM6 bit 8 on link down or 10/100 */
|
|
|
- ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
|
|
|
+ fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
|
|
|
+
|
|
|
+ if (!link || ((status & E1000_STATUS_SPEED_100) &&
|
|
|
+ (status & E1000_STATUS_FD)))
|
|
|
+ goto update_fextnvm6;
|
|
|
+
|
|
|
+ ret_val = e1e_rphy(hw, I217_INBAND_CTRL, ®);
|
|
|
+ if (ret_val)
|
|
|
+ return ret_val;
|
|
|
+
|
|
|
+ /* Clear link status transmit timeout */
|
|
|
+ reg &= ~I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK;
|
|
|
+
|
|
|
+ if (status & E1000_STATUS_SPEED_100) {
|
|
|
+ /* Set inband Tx timeout to 5x10us for 100Half */
|
|
|
+ reg |= 5 << I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
|
|
|
+
|
|
|
+ /* Do not extend the K1 entry latency for 100Half */
|
|
|
+ fextnvm6 &= ~E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
|
|
|
+ } else {
|
|
|
+ /* Set inband Tx timeout to 50x10us for 10Full/Half */
|
|
|
+ reg |= 50 <<
|
|
|
+ I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
|
|
|
+
|
|
|
+ /* Extend the K1 entry latency for 10 Mbps */
|
|
|
+ fextnvm6 |= E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret_val = e1e_wphy(hw, I217_INBAND_CTRL, reg);
|
|
|
+ if (ret_val)
|
|
|
+ return ret_val;
|
|
|
+
|
|
|
+update_fextnvm6:
|
|
|
+ ew32(FEXTNVM6, fextnvm6);
|
|
|
}
|
|
|
|
|
|
return ret_val;
|