aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/e1000e/ich8lan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/e1000e/ich8lan.c')
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c71
1 files changed, 70 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index dff7bff8b8e0..121a865c7fbd 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -782,6 +782,59 @@ release:
782} 782}
783 783
784/** 784/**
785 * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP
786 * @hw: pointer to the HW structure
787 * @link: link up bool flag
788 *
789 * When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
790 * preventing further DMA write requests. Workaround the issue by disabling
791 * the de-assertion of the clock request when in 1Gpbs mode.
792 **/
793static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
794{
795 u32 fextnvm6 = er32(FEXTNVM6);
796 s32 ret_val = 0;
797
798 if (link && (er32(STATUS) & E1000_STATUS_SPEED_1000)) {
799 u16 kmrn_reg;
800
801 ret_val = hw->phy.ops.acquire(hw);
802 if (ret_val)
803 return ret_val;
804
805 ret_val =
806 e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
807 &kmrn_reg);
808 if (ret_val)
809 goto release;
810
811 ret_val =
812 e1000e_write_kmrn_reg_locked(hw,
813 E1000_KMRNCTRLSTA_K1_CONFIG,
814 kmrn_reg &
815 ~E1000_KMRNCTRLSTA_K1_ENABLE);
816 if (ret_val)
817 goto release;
818
819 usleep_range(10, 20);
820
821 ew32(FEXTNVM6, fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK);
822
823 ret_val =
824 e1000e_write_kmrn_reg_locked(hw,
825 E1000_KMRNCTRLSTA_K1_CONFIG,
826 kmrn_reg);
827release:
828 hw->phy.ops.release(hw);
829 } else {
830 /* clear FEXTNVM6 bit 8 on link down or 10/100 */
831 ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
832 }
833
834 return ret_val;
835}
836
837/**
785 * e1000_check_for_copper_link_ich8lan - Check for link (Copper) 838 * e1000_check_for_copper_link_ich8lan - Check for link (Copper)
786 * @hw: pointer to the HW structure 839 * @hw: pointer to the HW structure
787 * 840 *
@@ -818,6 +871,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
818 return ret_val; 871 return ret_val;
819 } 872 }
820 873
874 /* Work-around I218 hang issue */
875 if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
876 (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
877 ret_val = e1000_k1_workaround_lpt_lp(hw, link);
878 if (ret_val)
879 return ret_val;
880 }
881
821 /* Clear link partner's EEE ability */ 882 /* Clear link partner's EEE ability */
822 hw->dev_spec.ich8lan.eee_lp_ability = 0; 883 hw->dev_spec.ich8lan.eee_lp_ability = 0;
823 884
@@ -3954,8 +4015,16 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
3954 4015
3955 phy_ctrl = er32(PHY_CTRL); 4016 phy_ctrl = er32(PHY_CTRL);
3956 phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; 4017 phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
4018
3957 if (hw->phy.type == e1000_phy_i217) { 4019 if (hw->phy.type == e1000_phy_i217) {
3958 u16 phy_reg; 4020 u16 phy_reg, device_id = hw->adapter->pdev->device;
4021
4022 if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
4023 (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
4024 u32 fextnvm6 = er32(FEXTNVM6);
4025
4026 ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
4027 }
3959 4028
3960 ret_val = hw->phy.ops.acquire(hw); 4029 ret_val = hw->phy.ops.acquire(hw);
3961 if (ret_val) 4030 if (ret_val)