summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib/mcbist
diff options
context:
space:
mode:
authorLouis Stermole <stermole@us.ibm.com>2018-02-07 10:47:16 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-02-19 11:33:13 -0500
commit9900129f86ae2fd82f59f643e71d15b5143959c2 (patch)
treebdcd5d1cb3bafd98f79adb728ea707eeca8c214c /src/import/chips/p9/procedures/hwp/memory/lib/mcbist
parent000f358355b25fe2e46abc44f20e47f315c34f72 (diff)
downloadtalos-hostboot-9900129f86ae2fd82f59f643e71d15b5143959c2.tar.gz
talos-hostboot-9900129f86ae2fd82f59f643e71d15b5143959c2.zip
Fix command gap calculation for MSS scrub to prevent truncation
Change-Id: Ifcebaf4b2d2145c3351d80c92b9c77f1ef8e4183 CQ:SW415825 RTC:187080 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/53554 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/53633 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/mcbist')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H100
1 files changed, 81 insertions, 19 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H
index 160db78ac..64743e365 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H
@@ -1742,6 +1742,79 @@ class program
}
///
+ /// @brief Calculate minimum command gap for BG_SCRUB
+ /// @param[in] i_target the target behind which the memory sits
+ /// @param[in] i_freq the DRAM frequency
+ /// @param[in] i_size the sum of all DIMM sizes
+ /// @param[out] o_min_cmd_gap the setting for MCBPARMQ_CFG_MIN_CMD_GAP
+ /// @param[out] o_timebase the setting for MCBPARMQ_CFG_MIN_GAP_TIMEBASE
+ ///
+ inline void calculate_min_cmd_gap( const fapi2::Target<T>& i_target,
+ const uint64_t i_freq,
+ const uint64_t i_size,
+ uint64_t& o_min_cmd_gap,
+ mss::states& o_timebase )
+ {
+ constexpr uint64_t l_seconds = SEC_IN_HOUR * BG_SCRUB_IN_HOURS;
+ constexpr uint64_t MIN_CMD_GAP = 0x001;
+
+ // Sanity check our inputs, just assert if bad since they come directly from eff_config
+ // this will prevent us from any divide by zero problems
+ if ((i_freq == 0) || (i_size == 0))
+ {
+ FAPI_ERR("received zero memory freq or size in calculate_min_cmd_gap");
+ fapi2::Assert(false);
+ }
+
+ // MIN CMD GAP = TOTAL CYCLES / TOTAL ADDRESSES
+ // TOTAL CYCLES = 12 hours x 60 min/hr x 60 sec/min x [DRAM freq] cycles/sec x
+ // 1/2 (MEM logic runs half DRAM freq)
+ const uint64_t l_mem_cycles_per_sec = (i_freq * T_PER_MT) / 2;
+ const uint64_t l_total_cycles = l_seconds * l_mem_cycles_per_sec;
+
+ // TOTAL ADDRESSES = sum over all dimms of ( [DIMM CAPACITY]/128B )
+ const uint64_t l_total_addresses = i_size * BYTES_PER_GB / 128;
+
+ const auto l_min_cmd_gap = l_total_cycles / l_total_addresses;
+
+ // If we're greater than the timebase, set the multiplier and divide down to get the gap setting
+ if (CMD_TIMEBASE < l_min_cmd_gap)
+ {
+ o_min_cmd_gap = l_min_cmd_gap / CMD_TIMEBASE;
+ o_timebase = mss::ON;
+ return;
+ }
+
+ // If we're greater than the max gap setting, get as close to 12 hours as we can instead of just truncating
+ if (l_min_cmd_gap > MAX_CMD_GAP)
+ {
+ // work backwards to calculate what the total scrub time would be with the highest cmd gap with no multiplier...
+ const uint64_t l_scrub_time_fff = (l_total_addresses * MAX_CMD_GAP) / l_mem_cycles_per_sec;
+ // and with the lowest cmd gap with the multiplier
+ const uint64_t l_scrub_time_001 = (l_total_addresses * CMD_TIMEBASE) / l_mem_cycles_per_sec;
+
+ if ((l_seconds - l_scrub_time_fff) > (l_scrub_time_001 - l_seconds))
+ {
+ FAPI_INF("%s gap is greater than the field will allow. Setting to: %03x", mss::c_str(i_target), MIN_CMD_GAP);
+ o_min_cmd_gap = MIN_CMD_GAP;
+ o_timebase = mss::ON;
+ }
+ else
+ {
+ FAPI_INF("%s gap is greater than the field will allow. Setting to: %03x", mss::c_str(i_target), MAX_CMD_GAP);
+ o_min_cmd_gap = MAX_CMD_GAP;
+ o_timebase = mss::OFF;
+ }
+
+ return;
+ }
+
+ // Else, we're good to just set the calculated gap value directly
+ o_min_cmd_gap = l_min_cmd_gap;
+ o_timebase = mss::OFF;
+ }
+
+ ///
/// @brief Change MCBIST Speed
/// @param[in] i_target the target behind which the memory sits
/// @param[in] i_speed the speed eunmeration
@@ -1762,31 +1835,20 @@ class program
uint64_t l_freq = 0;
uint64_t l_size = 0;
uint64_t l_min_cmd_gap = 0;
+ mss::states l_timebase = mss::OFF;
constexpr uint64_t l_seconds = SEC_IN_HOUR * BG_SCRUB_IN_HOURS;
FAPI_TRY( mss::freq(i_target, l_freq) );
FAPI_TRY( mss::eff_memory_size(i_target, l_size) );
- // MIN CMD GAP = TOTAL CYCLES / TOTAL ADDRESSES
- // TOTAL CYCLES = 12 hours x 60 min/hr x 60 sec/min x [DRAM freq] cycles/sec x
- // 1/2 (MEM logic runs half DRAM freq)
- // TOTAL ADDRESSES = sum over all dimms of ( [DIMM CAPACITY]/128B )
- l_min_cmd_gap = ((l_seconds * (l_freq * T_PER_MT)) / 2) / ((l_size * BYTES_PER_GB) / 128);
-
- FAPI_INF("setting bg scrub speed: %dMT/s, memory: %dGB, duration: %ds, gap: %d",
- l_freq, l_size, l_seconds, l_min_cmd_gap);
-
- if (CMD_TIMEBASE < l_min_cmd_gap)
- {
- change_min_cmd_gap(l_min_cmd_gap / CMD_TIMEBASE);
- change_min_gap_timebase(mss::ON);
- }
- else
- {
- change_min_cmd_gap(l_min_cmd_gap);
- change_min_gap_timebase(mss::OFF);
- }
+ calculate_min_cmd_gap(i_target, l_freq, l_size, l_min_cmd_gap, l_timebase);
+
+ FAPI_INF("%s setting bg scrub speed: %dMT/s, memory: %dGB, duration: %ds, gap: %d",
+ mss::c_str(i_target), l_freq, l_size, l_seconds, l_min_cmd_gap);
+
+ change_min_cmd_gap(l_min_cmd_gap);
+ change_min_gap_timebase(l_timebase);
return fapi2::FAPI2_RC_SUCCESS;
}
OpenPOWER on IntegriCloud