diff options
-rw-r--r-- | drivers/net/ethernet/intel/e1000e/ich8lan.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 56c4935b2578..ad9d8f2dd868 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c | |||
@@ -839,6 +839,94 @@ release: | |||
839 | } | 839 | } |
840 | 840 | ||
841 | /** | 841 | /** |
842 | * e1000_platform_pm_pch_lpt - Set platform power management values | ||
843 | * @hw: pointer to the HW structure | ||
844 | * @link: bool indicating link status | ||
845 | * | ||
846 | * Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like" | ||
847 | * GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed | ||
848 | * when link is up (which must not exceed the maximum latency supported | ||
849 | * by the platform), otherwise specify there is no LTR requirement. | ||
850 | * Unlike true-PCIe devices which set the LTR maximum snoop/no-snoop | ||
851 | * latencies in the LTR Extended Capability Structure in the PCIe Extended | ||
852 | * Capability register set, on this device LTR is set by writing the | ||
853 | * equivalent snoop/no-snoop latencies in the LTRV register in the MAC and | ||
854 | * set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB) | ||
855 | * message to the PMC. | ||
856 | **/ | ||
857 | static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link) | ||
858 | { | ||
859 | u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) | | ||
860 | link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND; | ||
861 | u16 lat_enc = 0; /* latency encoded */ | ||
862 | |||
863 | if (link) { | ||
864 | u16 speed, duplex, scale = 0; | ||
865 | u16 max_snoop, max_nosnoop; | ||
866 | u16 max_ltr_enc; /* max LTR latency encoded */ | ||
867 | s64 lat_ns; /* latency (ns) */ | ||
868 | s64 value; | ||
869 | u32 rxa; | ||
870 | |||
871 | if (!hw->adapter->max_frame_size) { | ||
872 | e_dbg("max_frame_size not set.\n"); | ||
873 | return -E1000_ERR_CONFIG; | ||
874 | } | ||
875 | |||
876 | hw->mac.ops.get_link_up_info(hw, &speed, &duplex); | ||
877 | if (!speed) { | ||
878 | e_dbg("Speed not set.\n"); | ||
879 | return -E1000_ERR_CONFIG; | ||
880 | } | ||
881 | |||
882 | /* Rx Packet Buffer Allocation size (KB) */ | ||
883 | rxa = er32(PBA) & E1000_PBA_RXA_MASK; | ||
884 | |||
885 | /* Determine the maximum latency tolerated by the device. | ||
886 | * | ||
887 | * Per the PCIe spec, the tolerated latencies are encoded as | ||
888 | * a 3-bit encoded scale (only 0-5 are valid) multiplied by | ||
889 | * a 10-bit value (0-1023) to provide a range from 1 ns to | ||
890 | * 2^25*(2^10-1) ns. The scale is encoded as 0=2^0ns, | ||
891 | * 1=2^5ns, 2=2^10ns,...5=2^25ns. | ||
892 | */ | ||
893 | lat_ns = ((s64)rxa * 1024 - | ||
894 | (2 * (s64)hw->adapter->max_frame_size)) * 8 * 1000; | ||
895 | if (lat_ns < 0) | ||
896 | lat_ns = 0; | ||
897 | else | ||
898 | do_div(lat_ns, speed); | ||
899 | |||
900 | value = lat_ns; | ||
901 | while (value > PCI_LTR_VALUE_MASK) { | ||
902 | scale++; | ||
903 | value = DIV_ROUND_UP(value, (1 << 5)); | ||
904 | } | ||
905 | if (scale > E1000_LTRV_SCALE_MAX) { | ||
906 | e_dbg("Invalid LTR latency scale %d\n", scale); | ||
907 | return -E1000_ERR_CONFIG; | ||
908 | } | ||
909 | lat_enc = (u16)((scale << PCI_LTR_SCALE_SHIFT) | value); | ||
910 | |||
911 | /* Determine the maximum latency tolerated by the platform */ | ||
912 | pci_read_config_word(hw->adapter->pdev, E1000_PCI_LTR_CAP_LPT, | ||
913 | &max_snoop); | ||
914 | pci_read_config_word(hw->adapter->pdev, | ||
915 | E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop); | ||
916 | max_ltr_enc = max_t(u16, max_snoop, max_nosnoop); | ||
917 | |||
918 | if (lat_enc > max_ltr_enc) | ||
919 | lat_enc = max_ltr_enc; | ||
920 | } | ||
921 | |||
922 | /* Set Snoop and No-Snoop latencies the same */ | ||
923 | reg |= lat_enc | (lat_enc << E1000_LTRV_NOSNOOP_SHIFT); | ||
924 | ew32(LTRV, reg); | ||
925 | |||
926 | return 0; | ||
927 | } | ||
928 | |||
929 | /** | ||
842 | * e1000_check_for_copper_link_ich8lan - Check for link (Copper) | 930 | * e1000_check_for_copper_link_ich8lan - Check for link (Copper) |
843 | * @hw: pointer to the HW structure | 931 | * @hw: pointer to the HW structure |
844 | * | 932 | * |
@@ -911,6 +999,15 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) | |||
911 | return ret_val; | 999 | return ret_val; |
912 | } | 1000 | } |
913 | 1001 | ||
1002 | if (hw->mac.type == e1000_pch_lpt) { | ||
1003 | /* Set platform power management values for | ||
1004 | * Latency Tolerance Reporting (LTR) | ||
1005 | */ | ||
1006 | ret_val = e1000_platform_pm_pch_lpt(hw, link); | ||
1007 | if (ret_val) | ||
1008 | return ret_val; | ||
1009 | } | ||
1010 | |||
914 | /* Clear link partner's EEE ability */ | 1011 | /* Clear link partner's EEE ability */ |
915 | hw->dev_spec.ich8lan.eee_lp_ability = 0; | 1012 | hw->dev_spec.ich8lan.eee_lp_ability = 0; |
916 | 1013 | ||