@@ -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:
200154template < >
201155fapi2 ::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 ),
0 commit comments