Skip to content

Commit

Permalink
Fix command gap calculation for MSS scrub to prevent truncation
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
stermole authored and dcrowell77 committed Feb 19, 2018
1 parent 000f358 commit 9900129
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 19 deletions.
100 changes: 81 additions & 19 deletions src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,79 @@ class program
return;
}

///
/// @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
Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ enum times
BG_SCRUB_IN_HOURS = 12,

CMD_TIMEBASE = 8192, ///< Represents the timebase multiplier for the MCBIST inter cmd gap
MAX_CMD_GAP = 4095, ///< Represents the maximum (non-multplied) time for MCBIST inter cmd gap
FULL_DLL_CAL_DELAY = 37382, ///< Full DLL calibration (in ddphy_nck cycles)
};

Expand Down

0 comments on commit 9900129

Please sign in to comment.