Commit cf8fb73c authored by Bruce Allan's avatar Bruce Allan Committed by Jeff Kirsher

e1000e: add support for LTR on I217/I218

Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like"
GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed
when link is up (which must not exceed the maximum latency supported
by the platform), otherwise specify there is no LTR requirement.
Unlike true-PCIe devices which set the LTR maximum snoop/no-snoop
latencies in the LTR Extended Capability Structure in the PCIe Extended
Capability register set, on this device LTR is set by writing the
equivalent snoop/no-snoop latencies in the LTRV register in the MAC and
set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB)
message to the PMC.
Signed-off-by: default avatarBruce Allan <bruce.w.allan@intel.com>
Tested-by: default avatarJeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 1fc06b0a
...@@ -838,6 +838,94 @@ static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link) ...@@ -838,6 +838,94 @@ static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
return ret_val; return ret_val;
} }
/**
* e1000_platform_pm_pch_lpt - Set platform power management values
* @hw: pointer to the HW structure
* @link: bool indicating link status
*
* Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like"
* GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed
* when link is up (which must not exceed the maximum latency supported
* by the platform), otherwise specify there is no LTR requirement.
* Unlike true-PCIe devices which set the LTR maximum snoop/no-snoop
* latencies in the LTR Extended Capability Structure in the PCIe Extended
* Capability register set, on this device LTR is set by writing the
* equivalent snoop/no-snoop latencies in the LTRV register in the MAC and
* set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB)
* message to the PMC.
**/
static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
{
u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) |
link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND;
u16 lat_enc = 0; /* latency encoded */
if (link) {
u16 speed, duplex, scale = 0;
u16 max_snoop, max_nosnoop;
u16 max_ltr_enc; /* max LTR latency encoded */
s64 lat_ns; /* latency (ns) */
s64 value;
u32 rxa;
if (!hw->adapter->max_frame_size) {
e_dbg("max_frame_size not set.\n");
return -E1000_ERR_CONFIG;
}
hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
if (!speed) {
e_dbg("Speed not set.\n");
return -E1000_ERR_CONFIG;
}
/* Rx Packet Buffer Allocation size (KB) */
rxa = er32(PBA) & E1000_PBA_RXA_MASK;
/* Determine the maximum latency tolerated by the device.
*
* Per the PCIe spec, the tolerated latencies are encoded as
* a 3-bit encoded scale (only 0-5 are valid) multiplied by
* a 10-bit value (0-1023) to provide a range from 1 ns to
* 2^25*(2^10-1) ns. The scale is encoded as 0=2^0ns,
* 1=2^5ns, 2=2^10ns,...5=2^25ns.
*/
lat_ns = ((s64)rxa * 1024 -
(2 * (s64)hw->adapter->max_frame_size)) * 8 * 1000;
if (lat_ns < 0)
lat_ns = 0;
else
do_div(lat_ns, speed);
value = lat_ns;
while (value > PCI_LTR_VALUE_MASK) {
scale++;
value = DIV_ROUND_UP(value, (1 << 5));
}
if (scale > E1000_LTRV_SCALE_MAX) {
e_dbg("Invalid LTR latency scale %d\n", scale);
return -E1000_ERR_CONFIG;
}
lat_enc = (u16)((scale << PCI_LTR_SCALE_SHIFT) | value);
/* Determine the maximum latency tolerated by the platform */
pci_read_config_word(hw->adapter->pdev, E1000_PCI_LTR_CAP_LPT,
&max_snoop);
pci_read_config_word(hw->adapter->pdev,
E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop);
max_ltr_enc = max_t(u16, max_snoop, max_nosnoop);
if (lat_enc > max_ltr_enc)
lat_enc = max_ltr_enc;
}
/* Set Snoop and No-Snoop latencies the same */
reg |= lat_enc | (lat_enc << E1000_LTRV_NOSNOOP_SHIFT);
ew32(LTRV, reg);
return 0;
}
/** /**
* e1000_check_for_copper_link_ich8lan - Check for link (Copper) * e1000_check_for_copper_link_ich8lan - Check for link (Copper)
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
...@@ -911,6 +999,15 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -911,6 +999,15 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
return ret_val; return ret_val;
} }
if (hw->mac.type == e1000_pch_lpt) {
/* Set platform power management values for
* Latency Tolerance Reporting (LTR)
*/
ret_val = e1000_platform_pm_pch_lpt(hw, link);
if (ret_val)
return ret_val;
}
/* Clear link partner's EEE ability */ /* Clear link partner's EEE ability */
hw->dev_spec.ich8lan.eee_lp_ability = 0; hw->dev_spec.ich8lan.eee_lp_ability = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment