Skip to content

Commit 3baa314

Browse files
brs332dcrowell77
authored andcommitted
Change sf_read to run multiple ports to end of MCBIST range
CQ: SW372805 Change-Id: Icc4f3d7846f1000d0aa9f05d4e1a68f9f9d12287 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34141 Tested-by: Jenkins Server <pfd-jenkins+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: JACOB L. HARVEY <jlharvey@us.ibm.com> Reviewed-by: Brian R. Silver <bsilver@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34144 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
1 parent 35fd358 commit 3baa314

File tree

5 files changed

+210
-55
lines changed

5 files changed

+210
-55
lines changed

src/import/chips/p9/procedures/hwp/memory/lib/mcbist/address.H

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ class address
107107

108108
address() = default;
109109

110+
static constexpr uint64_t LARGEST_ADDRESS = ~0 >> MAGIC_PAD;
111+
112+
// Used when accessing an integral value containing a port and DIMM combination
113+
static constexpr uint64_t DIMM_BIT = 63;
114+
static constexpr uint64_t PORT_START = 61;
115+
static constexpr uint64_t PORT_LEN = 2;
116+
110117
///
111118
/// @brief Construct an address from a uint64_t (scom'ed value)
112119
/// @param[in] i_value representing an address; say from a trap register
@@ -298,13 +305,42 @@ class address
298305

299306
///
300307
/// @brief Get the DIMM value for an address
301-
/// @return right-aligned uint64_t representing the vaule
308+
/// @return right-aligned uint64_t representing the value
302309
///
303310
inline uint64_t get_dimm() const
304311
{
305312
return (get_field<DIMM>() == true ? 1 : 0);
306313
}
307314

315+
///
316+
/// @brief Set the port and DIMM value for an address
317+
/// @param[in] i_value the value to set
318+
/// @return address& for method chaining
319+
/// @note Useful for indexing all ports/DIMM on a controller
320+
///
321+
inline address& set_port_dimm( const fapi2::buffer<uint64_t> i_value )
322+
{
323+
uint64_t l_read_port = 0;
324+
325+
i_value.extractToRight<PORT_START, PORT_LEN>(l_read_port);
326+
return set_dimm(i_value.getBit<DIMM_BIT>()).set_port(l_read_port);
327+
}
328+
329+
///
330+
/// @brief Get the port and DIMM value for an address
331+
/// @return right-aligned uint64_t representing the value
332+
/// @note Useful for indexing all ports/DIMM on a controller
333+
///
334+
inline uint64_t get_port_dimm() const
335+
{
336+
fapi2::buffer<uint64_t> l_value;
337+
338+
l_value.insertFromRight<PORT_START, PORT_LEN>(get_port());
339+
l_value.writeBit<DIMM_BIT>(get_field<DIMM>());
340+
341+
return l_value;
342+
}
343+
308344
///
309345
/// @brief Set the master rank value for an address
310346
/// @param[in] i_value the value to set

src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ class subtest_t
408408
/// @note The port number is relative to the MCBIST
409409
/// @return the port of the subtest
410410
///
411-
inline uint64_t get_port()
411+
inline uint64_t get_port() const
412412
{
413413
uint64_t l_port = 0;
414414
constexpr uint64_t l_len = (TT::COMPL_2ND_CMD - TT::COMPL_1ST_CMD) + 1;
@@ -420,7 +420,7 @@ class subtest_t
420420
/// @brief Get the DIMM from this subtest
421421
/// @return the DIMM this subtest has been configured for
422422
///
423-
inline uint64_t get_dimm()
423+
inline uint64_t get_dimm() const
424424
{
425425
return iv_mcbmr.template getBit<TT::COMPL_3RD_CMD>() ? 1 : 0;
426426
}

src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C

Lines changed: 156 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -145,52 +145,6 @@ fapi_try_exit:
145145
return fapi2::current_err;
146146
}
147147

148-
///
149-
/// @brief memdiags multi-port init helper
150-
/// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
151-
/// in subclassed constructors more easily.
152-
/// @return FAPI2_RC_SUCCESS iff everything ok
153-
///
154-
template<>
155-
fapi2::ReturnCode operation<TARGET_TYPE_MCBIST>::multi_port_init()
156-
{
157-
FAPI_INF("multi-port init %s", mss::c_str(iv_target));
158-
159-
// Deterimine which ports are functional and whether we can broadcast to them
160-
// TK on the broadcast BRS
161-
// Disable braodcast mode - disabled by default
162-
// For each functional port, setup 2 INIT subtests, one per DIMM select
163-
for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(iv_target))
164-
{
165-
// Run in ECC mode, 64B writes (superfast mode)
166-
for (const auto& d : mss::find_targets<TARGET_TYPE_DIMM>(p))
167-
{
168-
// Don't destroy the subtest passed in, copy it
169-
auto l_subtest = iv_subtest;
170-
171-
l_subtest.enable_port(mss::relative_pos<TARGET_TYPE_MCBIST>(p));
172-
l_subtest.enable_dimm(mss::index(d));
173-
iv_program.iv_subtests.push_back(l_subtest);
174-
FAPI_INF("adding superfast subtest for %s (dimm %d)", mss::c_str(d), mss::index(d));
175-
}
176-
}
177-
178-
// A operation which has an end address of 0 means 'to the end'
179-
if (iv_const.iv_end_address == 0)
180-
{
181-
iv_const.iv_start_address.get_range<mss::mcbist::address::DIMM>(iv_const.iv_end_address);
182-
}
183-
184-
// Configure the address range
185-
FAPI_TRY( mss::mcbist::config_address_range0(iv_target, iv_const.iv_start_address, iv_const.iv_end_address) );
186-
187-
// Initialize the common sections
188-
FAPI_TRY( base_init() );
189-
190-
fapi_try_exit:
191-
return fapi2::current_err;
192-
}
193-
194148
///
195149
/// @brief Single port initializer
196150
/// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
@@ -200,7 +154,7 @@ fapi_try_exit:
200154
template<>
201155
fapi2::ReturnCode operation<TARGET_TYPE_MCBIST>::single_port_init()
202156
{
203-
FAPI_INF("single port init");
157+
FAPI_INF("single port init %s", mss::c_str(iv_target));
204158

205159
const uint64_t l_relative_port_number = iv_const.iv_start_address.get_port();
206160
const uint64_t l_dimm_number = iv_const.iv_start_address.get_dimm();
@@ -230,8 +184,9 @@ fapi2::ReturnCode operation<TARGET_TYPE_MCBIST>::single_port_init()
230184
{
231185
iv_const.iv_start_address.get_sim_end_address(iv_const.iv_end_address);
232186
}
233-
else if (iv_const.iv_end_address == 0)
187+
else if (iv_const.iv_end_address == mss::mcbist::address::LARGEST_ADDRESS)
234188
{
189+
// Only the DIMM range as we don't want to cross ports.
235190
iv_const.iv_start_address.get_range<mss::mcbist::address::DIMM>(iv_const.iv_end_address);
236191
}
237192

@@ -245,6 +200,157 @@ fapi_try_exit:
245200
return fapi2::current_err;
246201
}
247202

203+
///
204+
/// @brief Helper to encapsualte the setting of multi-port address configurations
205+
/// @return FAPI2_RC_SUCCESS iff ok
206+
///
207+
template<>
208+
fapi2::ReturnCode operation<TARGET_TYPE_MCBIST>::multi_port_addr()
209+
{
210+
mss::mcbist::address l_end_of_start_port;
211+
mss::mcbist::address l_end_of_complete_port(mss::mcbist::address::LARGEST_ADDRESS);
212+
mss::mcbist::address l_start_of_end_port;
213+
214+
// The last address in the start port is the start address thru the "DIMM range" (all addresses left on this DIMM)
215+
iv_const.iv_start_address.get_range<mss::mcbist::address::DIMM>(l_end_of_start_port);
216+
217+
// The first address in the end port is the 0th address of the 0th DIMM on said port.
218+
l_start_of_end_port.set_port(iv_const.iv_end_address.get_port());
219+
220+
// Before we do anything else, fix up the address for sim. The end address given has to be limted so
221+
// we don't run too many cycles. Also, if there are intermediate ports the end addresses of those ports
222+
// need to be limited as well - they override the end address of a complete port (which is otherwise the
223+
// largest address.)
224+
if (iv_is_sim)
225+
{
226+
iv_const.iv_start_address.get_sim_end_address(l_end_of_start_port);
227+
mss::mcbist::address().get_sim_end_address(l_end_of_complete_port);
228+
l_start_of_end_port.get_sim_end_address(iv_const.iv_end_address);
229+
}
230+
231+
FAPI_INF("last addr in start port 0x%016lx first addr in end port 0x%016lx",
232+
uint64_t(l_end_of_start_port), uint64_t(l_start_of_end_port));
233+
234+
// We know we have three address configs: start address -> end of DIMM, 0 -> end of DIMM and 0 -> end address.
235+
FAPI_TRY( mss::mcbist::config_address_range0(iv_target, iv_const.iv_start_address, l_end_of_start_port) );
236+
FAPI_TRY( mss::mcbist::config_address_range1(iv_target, mss::mcbist::address(), l_end_of_complete_port) );
237+
FAPI_TRY( mss::mcbist::config_address_range2(iv_target, l_start_of_end_port, iv_const.iv_end_address) );
238+
239+
fapi_try_exit:
240+
return fapi2::current_err;
241+
}
242+
243+
///
244+
/// @brief memdiags multi-port init helper
245+
/// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
246+
/// in subclassed constructors more easily.
247+
/// @return FAPI2_RC_SUCCESS iff everything ok
248+
///
249+
template<>
250+
fapi2::ReturnCode operation<TARGET_TYPE_MCBIST>::multi_port_init()
251+
{
252+
FAPI_INF("multi-port init %s", mss::c_str(iv_target));
253+
254+
// Deterimine which ports are functional and whether we can broadcast to them
255+
// TK on the broadcast BRS
256+
// Disable braodcast mode - disabled by default
257+
258+
// We need to do three things here. One is to create a subtest which starts at start address and runs to
259+
// the end of the port. Next, create subtests to go from the start of the next port to the end of the
260+
// next port. Last we need a subtest which goes from the start of the last port to the end address specified
261+
// in the end address. Notice this may mean one subtest (start and end are on the same port) or it might
262+
// mean two subtests (start is one one port, end is on the next.) Or it might mean threee or more subtests.
263+
264+
// Get the port/DIMM information for the addresses. This is an integral value which allows us to index
265+
// all the DIMM across a controller.
266+
uint64_t l_portdimm_start_address = iv_const.iv_start_address.get_port_dimm();
267+
uint64_t l_portdimm_end_address = iv_const.iv_end_address.get_port_dimm();
268+
269+
FAPI_INF("start port/dimm: %d end port/dimm: %d", l_portdimm_start_address, l_portdimm_end_address);
270+
271+
// Since start address <= end address we can handle the single port case simply
272+
if (l_portdimm_start_address == l_portdimm_end_address)
273+
{
274+
// Single port case; simple.
275+
FAPI_TRY( single_port_init() );
276+
return fapi2::current_err;
277+
}
278+
279+
fapi2::Assert(l_portdimm_start_address < l_portdimm_end_address);
280+
281+
// If we're here we know start port < end port. We want to run one subtest (for each DIMM) from start_address
282+
// to the max range of the start address port, then one subtest (for each DIMM) for each port between the
283+
// start/end ports and one test (for each DIMM) from the start of the end port to the end address.
284+
285+
// Setup the address configurations
286+
FAPI_TRY( multi_port_addr() );
287+
288+
// Loop over all the DIMM on this MCBIST. Check the port/DIMM value for what to do.
289+
for (const auto& d : mss::find_targets<TARGET_TYPE_DIMM>(iv_target))
290+
{
291+
// The port/DIMM value for this DIMM is a three-bit field where the left-two are the relative position
292+
// in the controller and the right-most is the DIMMs index. We use this to decide how to process this dimm
293+
uint64_t l_rel_port = mss::relative_pos<TARGET_TYPE_MCBIST>(mss::find_target<TARGET_TYPE_MCA>(d));
294+
uint64_t l_dimm = mss::index(d);
295+
const uint64_t l_portdimm_this_dimm = (l_rel_port << 1) | l_dimm;
296+
297+
FAPI_INF("port/dimm %d, port/dimm start: %d", l_portdimm_this_dimm, l_portdimm_start_address);
298+
299+
// No need to process DIMM which are lower as they're not between the start and the end of the port.
300+
if (l_portdimm_this_dimm < l_portdimm_start_address)
301+
{
302+
continue;
303+
}
304+
305+
// Ok, we're gonna need to push on a subtest.
306+
auto l_subtest = iv_subtest;
307+
308+
l_subtest.enable_port(l_rel_port);
309+
l_subtest.enable_dimm(l_dimm);
310+
311+
// Ok this is the starting point. We know it's address selection is config0
312+
if (l_portdimm_this_dimm == l_portdimm_start_address)
313+
{
314+
l_subtest.change_addr_sel(0);
315+
}
316+
317+
// If this DIMM represents the end, we know that's address config2
318+
else if (l_portdimm_this_dimm == l_portdimm_end_address)
319+
{
320+
l_subtest.change_addr_sel(2);
321+
}
322+
323+
// Otherwise, we're someplace in between - address config1
324+
else
325+
{
326+
l_subtest.change_addr_sel(1);
327+
}
328+
329+
iv_program.iv_subtests.push_back(l_subtest);
330+
FAPI_INF("adding subtest for %s (port: %d dimm %d)", mss::c_str(iv_target), l_rel_port, l_dimm);
331+
}
332+
333+
// Here's an interesting problem. PRD (and others maybe) expect the operation to proceed in address-order.
334+
// That is, when PRD finds an address it stops on, it wants to continue from there "to the end." That means
335+
// we need to keep the subtests sorted, otherwise PRD could pass one subtest come upon a fail in a subsequent
336+
// subtest and re-test something it already passed. So we sort the resulting iv_subtest vector by port/DIMM
337+
// in the subtest.
338+
std::sort(iv_program.iv_subtests.begin(), iv_program.iv_subtests.end(),
339+
[](const decltype(iv_subtest)& a, const decltype(iv_subtest)& b) -> bool
340+
{
341+
uint64_t l_a_portdimm = (a.get_port() << 1) | a.get_dimm();
342+
uint64_t l_b_portdimm = (b.get_port() << 1) | b.get_dimm();
343+
344+
return l_a_portdimm > l_b_portdimm;
345+
});
346+
347+
// Initialize the common sections
348+
FAPI_TRY( base_init() );
349+
350+
fapi_try_exit:
351+
return fapi2::current_err;
352+
}
353+
248354
///
249355
/// @brief memdiags::continuous_scrub_operation constructor
250356
/// @param[in] i_target the target of the mcbist engine
@@ -427,7 +533,7 @@ fapi_try_exit:
427533
}
428534

429535
///
430-
/// @brief Super Fast Read to End of Port - used to run superfast read on all memory behind the target
536+
/// @brief Super Fast Read to End of MCBIST - used to run superfast read on all memory behind the target
431537
/// @tparam T the fapi2::TargetType of the target
432538
/// @param[in] i_target the target behind which all memory should be read
433539
/// @param[in] i_stop stop conditions
@@ -449,7 +555,7 @@ fapi2::ReturnCode sf_read( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
449555

450556
fapi2::ReturnCode l_rc;
451557
constraints l_const(i_stop, speed::LUDICROUS, i_end, i_address);
452-
sf_read_eop_operation<TARGET_TYPE_MCBIST> l_read_op(i_target, l_const, l_rc);
558+
sf_read_operation<TARGET_TYPE_MCBIST> l_read_op(i_target, l_const, l_rc);
453559

454560
FAPI_ASSERT( l_rc == FAPI2_RC_SUCCESS,
455561
fapi2::MSS_MEMDIAGS_SUPERFAST_READ_FAILED_TO_INIT().set_TARGET(i_target),

src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.H

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,13 @@ class operation
148148
///
149149
fapi2::ReturnCode multi_port_init();
150150

151+
///
152+
/// @brief memdiags multi-port address config helper
153+
/// Initializes the address configs needed for a multi port operation
154+
/// @return FAPI2_RC_SUCCESS iff everything ok
155+
///
156+
fapi2::ReturnCode multi_port_addr();
157+
151158
///
152159
/// @brief Single port initializer
153160
/// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes

src/import/chips/p9/procedures/hwp/memory/lib/mcbist/settings.H

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ struct constraints
713713
iv_end_boundary(NONE),
714714
iv_speed(LUDICROUS),
715715
iv_start_address(0),
716-
iv_end_address(0)
716+
iv_end_address(mcbist::address::LARGEST_ADDRESS)
717717
{
718718
}
719719

@@ -764,13 +764,19 @@ struct constraints
764764
const speed i_speed,
765765
const end_boundary i_end_boundary,
766766
const address& i_start_address,
767-
const address& i_end_address = mcbist::address(0) ):
767+
const address& i_end_address = mcbist::address(mcbist::address::LARGEST_ADDRESS) ):
768768
constraints(i_stop, i_start_address)
769769
{
770770
iv_end_boundary = i_end_boundary;
771771
iv_speed = i_speed;
772772
iv_end_address = i_end_address;
773773
FAPI_INF("setting up constraints with end boundary %d and speed 0x%x", i_end_boundary, i_speed);
774+
775+
// If our end address is 'before' our start address, make the end address the same as the start.
776+
if (iv_start_address > iv_end_address)
777+
{
778+
iv_end_address = iv_start_address;
779+
}
774780
}
775781

776782
stop_conditions iv_stop;

0 commit comments

Comments
 (0)