blob: d64991af5ccc78449a0d54ffea44c9b57a7d0273 [file] [log] [blame]
aalugorebe93ffe2015-09-18 15:53:46 -05001From 8afc07837b303e5621ba28fed8a070eba633475d Mon Sep 17 00:00:00 2001
2From: aalugore <aalugore@us.ibm.com>
3Date: Mon, 24 Aug 2015 13:42:24 -0500
4Subject: [PATCH] Function to set Nest Frequency based off DIMM memory
5 capability
6
7-Needed for 32x32GB DIMM support
8-Finds max capable frequency of system and all present DIMMs
9 and deconfigures any DIMM that cannot run at desired frequency
10-If necessary, Sets Nest Freq and triggers SBE update
11
12Change-Id: I9bba92f55f1b67ff4a15d79113f19d39272ec72d
13RTC:122884
14Depends-on:I1dca7196cd02a2704a238665b73b522c9e103936
15---
16 src/include/usr/hwpf/hwpf_reasoncodes.H | 4 +-
17 src/include/usr/isteps/istep12list.H | 4 +-
18 src/include/usr/sbe/sbeif.H | 16 +
19 src/include/usr/targeting/common/target.H | 11 +
20 src/include/util/algorithm.H | 18 +-
21 src/include/util/align.H | 17 +-
22 src/usr/hwpf/hwp/mc_config/mc_config.C | 437 ++++++++++++++++++++-
23 src/usr/hwpf/hwp/memory_attributes.xml | 12 +-
24 src/usr/hwpf/plat/fapiPlatUtil.C | 2 +-
25 src/usr/sbe/sbe_update.C | 62 +++
26 src/usr/targeting/common/target.C | 47 +++
27 .../targeting/common/xmltohb/attribute_types.xml | 10 +-
28 12 files changed, 608 insertions(+), 32 deletions(-)
29
30diff --git a/src/include/usr/hwpf/hwpf_reasoncodes.H b/src/include/usr/hwpf/hwpf_reasoncodes.H
31index e1a00da..ea326c1 100644
32--- a/src/include/usr/hwpf/hwpf_reasoncodes.H
33+++ b/src/include/usr/hwpf/hwpf_reasoncodes.H
34@@ -80,7 +80,9 @@ namespace fapi
35 MOD_PLAT_MVPD_GET_VLTG_BUCKET_ATTR = 0x26,
36 MOD_PLAT_ATTR_SVC_CEN_DQ_TO_DIMM_CONN_DQ = 0x27,
37 MOD_PLAT_ATTR_SVC_GET_MEM_ATTR_DATA = 0x28,
38-
39+ MOD_GET_WOF_FREQ_UPLIFT_SELECTED = 0x29,
40+ MOD_SET_NEST_FREQ = 0x2A,
41+ MOD_FIND_MAX_DMI_SPD = 0x2B,
42 };
43
44 /**
45diff --git a/src/include/usr/isteps/istep12list.H b/src/include/usr/isteps/istep12list.H
46index 2e724f2..f668733 100644
47--- a/src/include/usr/isteps/istep12list.H
48+++ b/src/include/usr/isteps/istep12list.H
49@@ -5,7 +5,7 @@
50 /* */
51 /* OpenPOWER HostBoot Project */
52 /* */
53-/* Contributors Listed Below - COPYRIGHT 2012,2014 */
54+/* Contributors Listed Below - COPYRIGHT 2012,2015 */
55 /* [+] Google Inc. */
56 /* [+] International Business Machines Corp. */
57 /* */
58@@ -105,6 +105,8 @@ const DepModInfo g_istep12Dependancies = {
59 #ifndef CONFIG_VPO_COMPILE
60 DEP_LIB(libmc_config.so),
61 #endif
62+ DEP_LIB(libsbe.so),
63+ DEP_LIB(libbuild_winkle_images.so),
64 NULL
65 }
66 };
67diff --git a/src/include/usr/sbe/sbeif.H b/src/include/usr/sbe/sbeif.H
68index b00e01f..ff397ca 100644
69--- a/src/include/usr/sbe/sbeif.H
70+++ b/src/include/usr/sbe/sbeif.H
71@@ -94,6 +94,22 @@ namespace SBE
72 */
73 errlHndl_t resolveProcessorSbeSeeproms();
74
75+ /**
76+ * @brief Determines whether we are on the Golden side or not
77+ *
78+ * @param[out] o_isGolden boolean, True if we are on Golden side, False
79+ * otherwise.
80+ *
81+ * @return errlHndl_t Error log handle on failure.
82+ *
83+ * NOTE: -Golden Side means we booted from the Golden Seeprom pointing
84+ * at the Golden side of PNOR.
85+ * -Using master processor to make this determination.
86+ */
87+
88+ errlHndl_t isGoldenSide( bool & o_isGolden );
89+
90+
91
92 } //end namespace SBE
93
94diff --git a/src/include/usr/targeting/common/target.H b/src/include/usr/targeting/common/target.H
95index 25e7be6..bf5b7da 100644
96--- a/src/include/usr/targeting/common/target.H
97+++ b/src/include/usr/targeting/common/target.H
98@@ -672,6 +672,17 @@ const char* Target::getAttrAsString() const
99 return attrToString<A>(l_attrValue);
100 }
101
102+// Function to set various frequency related attributes
103+/**
104+ * @brief - sets various attributes directly related to the nest frequency.
105+ *
106+ * @param[in] i_sys - top level system target to set attributes for
107+ * @param[in] i_newNestFreq - the new nest frequency to base all the attributes
108+ * off of.
109+ */
110+void setFrequencyAttributes(Target * i_sys, uint32_t i_newNestFreq);
111+
112+
113 // WARNING: The following #include imports any platform specific template
114 // specializations for getAttr and tryGetAttr
115 #include <targeting/adapters/targetadapter.H>
116diff --git a/src/include/util/algorithm.H b/src/include/util/algorithm.H
117index 54baa02..dac0f47 100644
118--- a/src/include/util/algorithm.H
119+++ b/src/include/util/algorithm.H
120@@ -5,7 +5,9 @@
121 /* */
122 /* OpenPOWER HostBoot Project */
123 /* */
124-/* COPYRIGHT International Business Machines Corp. 2012,2014 */
125+/* Contributors Listed Below - COPYRIGHT 2012,2015 */
126+/* [+] International Business Machines Corp. */
127+/* */
128 /* */
129 /* Licensed under the Apache License, Version 2.0 (the "License"); */
130 /* you may not use this file except in compliance with the License. */
131@@ -52,6 +54,20 @@ namespace Util
132 static const T value = (a > b) ? a : b;
133 };
134
135+ /**
136+ * @brief - utility function that determines if a given number is
137+ * power of 2.
138+ *
139+ * @param[in] i_num - given number.
140+ *
141+ * @return bool - True if the number is a power of 2, False otherwise.
142+ */
143+ template <typename T>
144+ bool isPow2(T i_num)
145+ {
146+ return (!(i_num & (i_num-1)));
147+ }
148+
149 };
150 };
151 #endif
152diff --git a/src/include/util/align.H b/src/include/util/align.H
153index e0132b2..10a8369 100644
154--- a/src/include/util/align.H
155+++ b/src/include/util/align.H
156@@ -51,18 +51,7 @@
157 #define ALIGN_MEGABYTE(u) (ALIGN_X(u,MEGABYTE))
158 #define ALIGN_MEGABYTE_DOWN(u) (ALIGN_DOWN_X(u,MEGABYTE))
159
160-// Returns a number that is aligned to the next highest power of 2 number of
161-// pages for the given buffer.
162-#define ALIGN_TO_NEXT_POWER_OF_TWO_PAGES(b) ({\
163- unsigned int v = ALIGN_PAGE(b)/PAGE_SIZE;\
164- v--;\
165- v |= v >> 1;\
166- v |= v >> 2;\
167- v |= v >> 4;\
168- v |= v >> 8;\
169- v |= v >> 16;\
170- v++;\
171- v * PAGE_SIZE;\
172- })
173-
174+// Return a number rounded to the next power of two.
175+#define ALIGN_POW2(u) ((u&(u-1)) ? 1 << (64 - __builtin_clzl(u)) : u)
176+#define ALIGN_POW2_DOWN(u) (u ? 1 << (63 - __builtin_clzl(u)) : 0)
177 #endif
178diff --git a/src/usr/hwpf/hwp/mc_config/mc_config.C b/src/usr/hwpf/hwp/mc_config/mc_config.C
179index b2bc2f1..f29ee7c 100644
180--- a/src/usr/hwpf/hwp/mc_config/mc_config.C
181+++ b/src/usr/hwpf/hwp/mc_config/mc_config.C
182@@ -44,16 +44,19 @@
183
184 #include <trace/interface.H>
185 #include <initservice/taskargs.H>
186+#include <initservice/initserviceif.H>
187 #include <errl/errlentry.H>
188
189 #include <hwpisteperror.H>
190+#include <hwpf/hwpf_reasoncodes.H>
191 #include <errl/errludtarget.H>
192
193 #include <initservice/isteps_trace.H>
194-
195+#include <sbe/sbeif.H>
196 // targeting support
197 #include <targeting/common/commontargeting.H>
198 #include <targeting/common/utilFilter.H>
199+#include <attributetraits.H>
200
201 // fapi support
202 #include <fapi.H>
203@@ -79,6 +82,8 @@
204 #include "mss_volt/mss_volt_dimm_count.H"
205
206 #include <config.h>
207+#include <util/align.H>
208+#include <util/algorithm.H>
209
210 namespace MC_CONFIG
211 {
212@@ -129,7 +134,8 @@ void set_eff_config_attrs_helper( const EFF_CONFIG_ATTRIBUTES_BASE i_base,
213 // Get Node Target
214 TARGETING::Target* sysTgt = NULL;
215 TARGETING::targetService().getTopLevelTarget(sysTgt);
216- assert(sysTgt != NULL,"System target was NULL.");
217+ assert(sysTgt != NULL,"set_eff_config_attrs_helper: "
218+ "System target was NULL.");
219
220 TARGETING::TargetHandleList l_nodeList;
221
222@@ -467,7 +473,8 @@ errlHndl_t setMemoryVoltageDomainOffsetVoltage()
223
224 TARGETING::Target* pSysTarget = NULL;
225 TARGETING::targetService().getTopLevelTarget(pSysTarget);
226- assert(pSysTarget != NULL,"System target was NULL.");
227+ assert(pSysTarget != NULL,"setMemoryVoltageDomainOffsetVoltage: "
228+ "System target was NULL.");
229
230 typename AttributeTraits< OFFSET_DISABLEMENT_ATTR >::Type
231 disableOffsetVoltage =
232@@ -717,13 +724,16 @@ void call_mss_volt_hwp (std::vector<TARGETING::ATTR_VMEM_ID_type>& i_VmemList,
233 l_membufFapiTargets.push_back( l_membuf_fapi_target );
234 }
235 }
236+
237+ TRACDCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
238+ "Calling mss_volt_hwp...");
239 FAPI_INVOKE_HWP(l_err, mss_volt_hwp, l_membufFapiTargets);
240
241 // process return code.
242 if ( l_err )
243 {
244 TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
245- "ERROR 0x%.8X: mss_volt_dimm_count HWP( ) ",
246+ "ERROR 0x%.8X: mss_volt HWP( ) ",
247 l_err->reasonCode());
248
249 // Create IStep error log and cross reference to error that occurred
250@@ -872,7 +882,411 @@ void* call_mss_volt( void *io_pArgs )
251
252 return l_StepError.getErrorHandle();
253 }
254+/**
255+ * @brief - this utility function takes in the frequency in
256+ * ATTR_MRW_NEST_CAPABLE_FREQUENCIES_SYS and returns the corresponding
257+ * dmi bus speed from ATTR_MSS_NEST_CAPABLE_FREQUENCIES
258+ *
259+ * @param[in] i_freq - the input frequency
260+ * @param[in/out] io_speed - the corresponding dmi bus speed
261+ */
262+void sysFreq_to_dmiSpeed(ATTR_MRW_NEST_CAPABLE_FREQUENCIES_SYS_type i_freq,
263+ ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type & io_speed)
264+{
265+ switch(i_freq)
266+ {
267+ case TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_UNSUPPORTED_FREQ:
268+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"Unsupported nest freq!");
269+ io_speed = 0;
270+ break;
271+ case TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2000_MHZ:
272+ io_speed=fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_8_0G;
273+ break;
274+ case TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2400_MHZ:
275+ io_speed=fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_9_6G;
276+ break;
277+ case TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2000_MHZ_OR_2400_MHZ:
278+ io_speed=fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_8_0G_OR_9_6G;
279+ break;
280+ default:
281+ io_speed = 0;
282+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"Invalid nest freq!");
283+ }
284+}
285
286+/**
287+ * @brief - this utility function takes in the dmi bus speed enumeration
288+ * value as described in MSS_NEST_CAPABLE_FREQUENCIES and outputs
289+ * the actual corresponding nest frequency in MHz supported by the
290+ * given dmi bus speed.
291+ *
292+ * @param[in] i_speed - the input dmi bus speed
293+ * @param[in/out] io_freq - the corresponding frequency in MHz
294+ *
295+ */
296+void dmiSpeed_to_sysFreq(ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type i_speed,
297+ ATTR_NEST_FREQ_MHZ_type & io_freq)
298+{
299+ switch(i_speed)
300+ {
301+ case fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_8_0G:
302+ io_freq = 2000;
303+ break;
304+ case fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_9_6G:
305+ io_freq = 2400;
306+ break;
307+ default:
308+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Invalid dmi speed!");
309+ io_freq = 0;
310+ }
311+}
312+
313+
314+
315+//
316+// calloutChildDimms
317+//
318+void calloutChildDimms(errlHndl_t & io_errl, const TARGETING::Target * i_membuf)
319+{
320+ TargetHandleList l_dimmList;
321+
322+ // Get child dimms
323+ getChildAffinityTargets( l_dimmList,
324+ i_membuf,
325+ CLASS_NA,
326+ TYPE_DIMM );
327+
328+ if( !l_dimmList.empty())
329+ {
330+ // iterate over the DIMMs and call them out
331+ TargetHandleList::iterator l_iter = l_dimmList.begin();
332+
333+ for(;l_iter != l_dimmList.end(); ++l_iter)
334+ {
335+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
336+ "Calling out DIMM Target huid = %x",
337+ get_huid(*l_iter));
338+
339+ io_errl->addHwCallout( *l_iter,
340+ HWAS::SRCI_PRIORITY_MED,
341+ HWAS::DELAYED_DECONFIG,
342+ HWAS::GARD_NULL );
343+ }
344+ }
345+ else
346+ {
347+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "No child DIMMs found!");
348+ }
349+}
350+
351+
352+// TODO RTC 135720 - Support for mixed DIMM configuration with 32GB DIMMs.
353+
354+/**
355+ * @brief - Recursive utility function for finding the max dmi
356+ * bus speed to run at based on the nest dmi bus speed
357+ * and the membuf's dmi bus speed
358+ *
359+ * @param[in] i_iter - Iterator over the list of membufs.
360+ * @param[in] i_membufs - Pointer to the list of membufs.
361+ * @param[in/out] io_currentMaxSpeed - The speed to run at will be returned here
362+ * @param[in] i_capableNestDmiBusSpeed - The nest capable dmi bus speed.
363+ */
364+void findMaxSpdAndDeconfigIncompatible(TargetHandleList::iterator i_iter,
365+ TargetHandleList * i_membufs,
366+ ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type & io_currentMaxSpeed,
367+ ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type i_capableNestDmiBusSpeed )
368+{
369+ do
370+ {
371+ // Base Case: If we are at the end of the membuf list return
372+ if(i_iter == i_membufs->end())
373+ {
374+ // find the left most bit of the max speed found. This bit
375+ // represents the highest dmi bus speed setting we can support
376+ // across the nest and all membufs and the speed we will boot with.
377+ io_currentMaxSpeed = ALIGN_POW2_DOWN(io_currentMaxSpeed);
378+ break;
379+ }
380+
381+ // Get the current membuf's dmi bus speed
382+ ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_currentMembufSpd =
383+ (*i_iter)->getAttr<TARGETING::ATTR_MSS_NEST_CAPABLE_FREQUENCIES>();
384+
385+ // update current max speed.
386+ // Max is restricted by nest capable dmi bus speed
387+ if(((l_currentMembufSpd & i_capableNestDmiBusSpeed) != 0) &&
388+ (l_currentMembufSpd > io_currentMaxSpeed))
389+ {
390+ io_currentMaxSpeed = l_currentMembufSpd;
391+ }
392+
393+ //Save the current membuf for when we come back from recursive call.
394+ TARGETING::Target * l_currentMembuf = (*i_iter);
395+
396+ // Recursive call to go down the list of membufs and find the max
397+ // capable dmi speed across the nest and membufs.
398+ findMaxSpdAndDeconfigIncompatible(++i_iter,
399+ i_membufs,
400+ io_currentMaxSpeed,
401+ i_capableNestDmiBusSpeed );
402+
403+ // deconfigure any membufs with incompatible
404+ // speeds on the way up the stack
405+ if((l_currentMembufSpd & io_currentMaxSpeed) == 0)
406+ {
407+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
408+ "Deconfiguring Membuf Huid: %X, membuf speed: %d",
409+ TARGETING::get_huid(l_currentMembuf),
410+ l_currentMembufSpd);
411+ // Membuf has incompatible frequency. Deconfigure it.
412+ /*@
413+ * @errortype
414+ * @moduleid MOD_FIND_MAX_DMI_SPD
415+ * @reasoncode RC_INVALID_FREQ
416+ * @userdata1 HUID of membuf
417+ * @userdata2 [0:7] membuf frequency enumeration value
418+ * @userdata2 [8:15] dmi bus speed enumeration value
419+ * @devdesc Invalid nest frequency found for given membuf
420+ * @custdesc Invalid memory configuration
421+ */
422+ errlHndl_t l_err = new ERRORLOG::ErrlEntry(
423+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
424+ fapi::MOD_FIND_MAX_DMI_SPD,
425+ fapi::RC_INVALID_FREQ,
426+ TARGETING::get_huid(l_currentMembuf),
427+ TO_UINT64(TWO_UINT8_TO_UINT16
428+ (l_currentMembufSpd,
429+ i_capableNestDmiBusSpeed)));
430+
431+ l_err->addHwCallout(l_currentMembuf, HWAS::SRCI_PRIORITY_HIGH,
432+ HWAS::DELAYED_DECONFIG,
433+ HWAS::GARD_NULL );
434+ l_err->addProcedureCallout(
435+ HWAS::EPUB_PRC_MEMORY_PLUGGING_ERROR,
436+ HWAS::SRCI_PRIORITY_HIGH );
437+
438+
439+ // add hw callouts for current membuf child DIMMs
440+ calloutChildDimms( l_err, l_currentMembuf );
441+
442+ errlCommit( l_err, HWPF_COMP_ID );
443+ l_err = NULL;
444+ }
445+ }while( 0 );
446+}
447+
448+
449+//
450+// setNestBasedOffDimms
451+//
452+errlHndl_t setNestBasedOffDimms()
453+{
454+ TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ENTER_MRK"mc_config::setNestBasedOffDimms()");
455+ errlHndl_t l_err = NULL;
456+ bool l_isGoldenSide = false;
457+ ATTR_MRW_NEST_CAPABLE_FREQUENCIES_SYS_type l_capableNestFreq =
458+ MRW_NEST_CAPABLE_FREQUENCIES_SYS_UNSUPPORTED_FREQ;
459+
460+ ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_selectedBootSpeed =
461+ fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_NONE;
462+
463+ ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_capableNestDmiBusSpeed =
464+ fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_NONE;
465+
466+ ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_compatibleSpeed =
467+ fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_NONE;
468+
469+ ATTR_NEST_FREQ_MHZ_type l_maxFreqMhz = 0;
470+
471+ l_isGoldenSide = false;
472+
473+ do
474+ {
475+ // First, get the systems capable nest frequency. If 0, then stick with
476+ // already set nest frequency
477+ TARGETING::Target * l_sys = NULL;
478+ targetService().getTopLevelTarget(l_sys);
479+
480+ uint32_t l_currentSysNestFreq =
481+ l_sys->getAttr<TARGETING::ATTR_NEST_FREQ_MHZ>();
482+
483+ // Check to see if we booted from the Golden side
484+ l_err = SBE::isGoldenSide(l_isGoldenSide);
485+
486+ if(l_err)
487+ {
488+ // Error getting Golden side. Proceeding as if booting from safe Golden side
489+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
490+ ERR_MRK"setNestBasedOffDimms::isGoldenSide returned an error");
491+ errlCommit( l_err, HWPF_COMP_ID );
492+ l_isGoldenSide = true;
493+ }
494+
495+ if(!l_isGoldenSide)
496+ {
497+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
498+ INFO_MRK"Booting from normal side. use "
499+ "MRW_NEST_CAPABLE_FREQUENCIES_SYS to calculate best freq "
500+ "across membufs");
501+ l_capableNestFreq = l_sys->getAttr
502+ <ATTR_MRW_NEST_CAPABLE_FREQUENCIES_SYS>();
503+ }
504+ else
505+ {
506+ // We booted using the Golden Side. Use NEST_FREQ_MHZ
507+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
508+ INFO_MRK"Booting from Golden Side. Use default NEST_FREQ"
509+ "to calculate best freq across membufs");
510+ if(l_currentSysNestFreq == 2000)
511+ {
512+ l_capableNestFreq =
513+ TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2000_MHZ;
514+ }
515+ else if( l_currentSysNestFreq == 2400 )
516+ {
517+ l_capableNestFreq =
518+ TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2400_MHZ;
519+ }
520+ else
521+ {
522+ l_capableNestFreq =
523+ TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_UNSUPPORTED_FREQ;
524+ }
525+
526+ }
527+
528+ // convert the frequency to its corresponding dmi bus speed
529+ sysFreq_to_dmiSpeed( l_capableNestFreq, l_capableNestDmiBusSpeed );
530+
531+ if(!l_capableNestDmiBusSpeed)
532+ {
533+ // Unknown frequency was given to sysFreq_to_dmiSpeed
534+ // break out of function and proceed with value already in
535+ // ATTR_NEST_FREQ_MHZ
536+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"Invalid dmi speed. Proceeding with default value in NEST_FREQ_MHZ.");
537+ break;
538+ }
539+
540+ // Get a list of all the membufs
541+ TargetHandleList l_membufs;
542+ TARGETING::getAllChips(l_membufs, TYPE_MEMBUF);
543+ TargetHandleList::iterator l_iter = l_membufs.begin();
544+
545+
546+ // If the nest capable dmi bus speed can only support one setting,
547+ // that speed is the speed we want to boot with.
548+ // Deconfigure all membufs with incompatible speeds
549+ if(Util::Algorithm::isPow2(l_capableNestDmiBusSpeed))
550+ {
551+ // We are forced to boot with the nest freq.
552+ // Save boot freq for later.
553+ l_selectedBootSpeed = l_capableNestDmiBusSpeed;
554+
555+
556+ ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_membufDmiBusSpeed = 0;
557+ for(;l_iter != l_membufs.end(); ++l_iter )
558+ {
559+ l_membufDmiBusSpeed = (*l_iter)->getAttr
560+ <TARGETING::ATTR_MSS_NEST_CAPABLE_FREQUENCIES>();
561+
562+ // if the intersection of the membuf's and nest's dmi speed
563+ // is zero, the membuf is incompatible with the nest and must be
564+ // deconfigured.
565+ l_compatibleSpeed = l_membufDmiBusSpeed &
566+ l_capableNestDmiBusSpeed;
567+
568+ if(l_compatibleSpeed ==
569+ fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_NONE )
570+ {
571+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
572+ "Deconfiguring Membuf Huid: %X, membuf speed: %d",
573+ TARGETING::get_huid(*l_iter),
574+ l_membufDmiBusSpeed);
575+ // Membuf has incompatible frequency. Deconfigure it.
576+ /*@
577+ * @errortype
578+ * @moduleid MOD_SET_NEST_FREQ
579+ * @reasoncode RC_INVALID_FREQ
580+ * @userdata1 HUID of membuf
581+ * @userdata2 [0:7] membuf frequency enumeration value
582+ * @userdata2 [8:15] dmi bus speed enumeration value
583+ * @devdesc Invalid nest found for given membuf
584+ * @custdesc Invalid memory configuration
585+ */
586+ l_err = new ERRORLOG::ErrlEntry(
587+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
588+ fapi::MOD_SET_NEST_FREQ,
589+ fapi::RC_INVALID_FREQ,
590+ TARGETING::get_huid(*l_iter),
591+ TO_UINT64(TWO_UINT8_TO_UINT16
592+ (l_membufDmiBusSpeed,
593+ l_capableNestDmiBusSpeed)));
594+
595+ l_err->addHwCallout(*l_iter, HWAS::SRCI_PRIORITY_HIGH,
596+ HWAS::DELAYED_DECONFIG,
597+ HWAS::GARD_NULL );
598+
599+
600+ // add hw callouts for current membufs child DIMMs
601+ calloutChildDimms( l_err, *l_iter);
602+
603+ errlCommit( l_err, HWPF_COMP_ID );
604+ l_err = NULL;
605+ continue;
606+ }
607+
608+ } // end for-loop
609+
610+ }
611+ else
612+ {
613+ // The nest supports multiple frequencies. Find the max dmi bus
614+ // speed shared by the nest and at least 1 membuf and boot with that
615+ // speed.
616+ findMaxSpdAndDeconfigIncompatible(l_iter,
617+ &l_membufs,
618+ l_selectedBootSpeed,
619+ l_capableNestDmiBusSpeed);
620+
621+ }
622+
623+ //Convert the selected boot speed to frequency
624+ dmiSpeed_to_sysFreq(l_selectedBootSpeed, l_maxFreqMhz);
625+
626+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
627+ "The max supported frequency across the processor and all dimms "
628+ "is %d", l_maxFreqMhz );
629+
630+ if( l_maxFreqMhz == l_currentSysNestFreq)
631+ {
632+ //do nothing. go with current Nest freq, break.
633+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
634+ "Nest did not need to change. Proceeding with default NEST_FREQ");
635+ break;
636+ }
637+ else
638+ {
639+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
640+ "DIMM config determined NEST_FREQ needs to be changed to %d",
641+ l_maxFreqMhz );
642+ //set all the attributes and trigger an sbe update
643+ TARGETING::setFrequencyAttributes(l_sys, l_maxFreqMhz);
644+ //trigger sbe update so we can update all the frequency attributes
645+ l_err = SBE::updateProcessorSbeSeeproms(
646+ SBE::SBE_UPDATE_ONLY_CHECK_NEST_FREQ);
647+
648+ if( l_err )
649+ {
650+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
651+ "Error triggering sbe update.");
652+ }
653+ }
654+ }while( 0 );
655+
656+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "setNestBasedOffDimms exit" );
657+ return l_err;
658+}
659 //
660 // Wrapper function to call mss_freq
661 //
662@@ -931,6 +1345,21 @@ void* call_mss_freq( void *io_pArgs )
663 }
664 } // End memBuf loop
665
666+ if(! INITSERVICE::spBaseServicesEnabled() )
667+ {
668+ //set nest frequency based off present membufs
669+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
670+ INFO_MRK"Setting Nest Frequency based off Membuf capability.");
671+ l_err = setNestBasedOffDimms();
672+
673+ if( l_err )
674+ {
675+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
676+ ERR_MRK"Error: call_mss_freq()::setNestBasedOffDimms()");
677+ l_StepError.addErrorDetails(l_err);
678+ }
679+ }
680+
681 TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_mss_freq exit" );
682
683 return l_StepError.getErrorHandle();
684diff --git a/src/usr/hwpf/hwp/memory_attributes.xml b/src/usr/hwpf/hwp/memory_attributes.xml
685index b4059a2..df3a2ef 100644
686--- a/src/usr/hwpf/hwp/memory_attributes.xml
687+++ b/src/usr/hwpf/hwp/memory_attributes.xml
688@@ -1,7 +1,7 @@
689 <!-- IBM_PROLOG_BEGIN_TAG -->
690 <!-- This is an automatically generated prolog. -->
691 <!-- -->
692-<!-- $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/xml/attribute_info/memory_attributes.xml,v $ -->
693+<!-- $Source: src/usr/hwpf/hwp/memory_attributes.xml $ -->
694 <!-- -->
695 <!-- OpenPOWER HostBoot Project -->
696 <!-- -->
697@@ -23,7 +23,7 @@
698 <!-- -->
699 <!-- IBM_PROLOG_END_TAG -->
700 <attributes>
701-<!-- $Id: memory_attributes.xml,v 1.159 2015/09/09 18:10:53 thi Exp $ -->
702+<!-- $Id: memory_attributes.xml,v 1.159AL_custom 2014/11/18 17:35:29 aalugore Exp $ -->
703 <!-- DO NOT EDIT THIS FILE DIRECTLY PLEASE UPDATE THE ODS FILE AND FOLLOW THE INSTRUCTION TAB -->
704 <!-- PLEASE SEE MARK BELLOWS (BELLOWS.IBM.COM) OR OTHERS ON MEMORY TEAM FOR HELP -->
705 <!-- *********************************************************************** -->
706@@ -108,7 +108,7 @@ Set by: PLL settings written by Dave Cadigan</description>
707 <odmChangeable/>
708 <persistRuntime/>
709 </attribute>
710-
711+
712 <attribute>
713 <id>ATTR_MSS_DIMM_MFG_ID_CODE</id>
714 <targetType>TARGET_TYPE_MBA_CHIPLET</targetType>
715@@ -3051,8 +3051,8 @@ Will be set at an MBA level with one policy to be used</description>
716 <writeable/>
717 <odmVisable/>
718 <odmChangeable/>
719- <enum>8_0G = 1, 9_6G = 2</enum>
720-</attribute>
721+ <enum>NONE = 0, 8_0G = 1, 9_6G = 2, 8_0G_OR_9_6G = 3</enum>
722+</attribute>
723
724 <attribute>
725 <id>ATTR_MRW_STRICT_MBA_PLUG_RULE_CHECKING</id>
726@@ -3425,7 +3425,7 @@ Will be set at an MBA level with one policy to be used</description>
727 <valueType>uint32</valueType>
728 <platInit/>
729 <odmVisable/>
730-</attribute>
731+</attribute>
732
733 <attribute>
734 <id>ATTR_MRW_MEM_SENSOR_CACHE_ADDR_MAP</id>
735diff --git a/src/usr/hwpf/plat/fapiPlatUtil.C b/src/usr/hwpf/plat/fapiPlatUtil.C
736index d03b670..269c36f 100644
737--- a/src/usr/hwpf/plat/fapiPlatUtil.C
738+++ b/src/usr/hwpf/plat/fapiPlatUtil.C
739@@ -334,7 +334,7 @@ void* fapiPlatMalloc(size_t s)
740 {
741 if (s > PAGE_SIZE)
742 {
743- s = ALIGN_TO_NEXT_POWER_OF_TWO_PAGES(s);
744+ s = PAGE_SIZE * ALIGN_POW2(ALIGN_PAGE(s) / PAGE_SIZE);
745 }
746 return malloc(s);
747 }
748diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C
749index 1faad63..237838f 100644
750--- a/src/usr/sbe/sbe_update.C
751+++ b/src/usr/sbe/sbe_update.C
752@@ -3976,6 +3976,68 @@ namespace SBE
753
754 }
755
756+/////////////////////////////////////////////////////////////////////
757+ errlHndl_t isGoldenSide( bool & o_isGolden )
758+ {
759+ errlHndl_t l_errl = NULL;
760+ o_isGolden = false;
761+
762+#ifndef CONFIG_SBE_UPDATE_SEQUENTIAL
763+ do
764+ {
765+ // Get the master processor
766+ TARGETING::Target * l_masterProc = NULL;
767+ TARGETING::targetService().masterProcChipTargetHandle(l_masterProc);
768+ assert( l_masterProc != NULL );
769+
770+ sbeSeepromSide_t l_currentSide = SBE_SEEPROM_INVALID;
771+
772+ // Get Seeprom side
773+ l_errl = getSbeBootSeeprom(l_masterProc, l_currentSide);
774+
775+ if( l_errl )
776+ {
777+ TRACFCOMP( g_trac_sbe, ERR_MRK
778+ "isGoldenSide() - Error returned "
779+ "from getSbeBootSeeprom() "
780+ "rc=0x%.4X, Target UID=0x%X",
781+ l_errl->reasonCode(),
782+ TARGETING::get_huid(l_masterProc));
783+ break;
784+ }
785+
786+ //Get PNOR Side
787+ PNOR::SideId l_pnorSide = PNOR::WORKING;
788+ PNOR::SideInfo_t l_sideInfo;
789+
790+ l_errl = PNOR::getSideInfo( l_pnorSide, l_sideInfo );
791+
792+ if( l_errl )
793+ {
794+ TRACFCOMP(g_trac_sbe, ERR_MRK
795+ "isGoldenSide() - Error returned "
796+ "from PNOR::getSideInfo() "
797+ "rc=0x%.4X, Target UID=0x%X",
798+ l_errl->reasonCode(),
799+ TARGETING::get_huid( l_masterProc ));
800+ break;
801+ }
802+
803+ // SBE_SEEPROM1 by itself does not imply golden side.
804+ // cross reference sbe side with pnor side to make sure.
805+ if(( l_currentSide == SBE_SEEPROM1 ) &&
806+ (( l_sideInfo.isGolden ) || (l_sideInfo.hasOtherSide == false )))
807+ {
808+ TRACUCOMP(g_trac_sbe, INFO_MRK
809+ "sbe_update.C::isGoldenSide() - "
810+ "Booted from Golden side!");
811+ o_isGolden = true;
812+ }
813+
814+ }while( 0 );
815+#endif
816+ return l_errl;
817+ }
818
819
820 /////////////////////////////////////////////////////////////////////
821diff --git a/src/usr/targeting/common/target.C b/src/usr/targeting/common/target.C
822index 2248283..559fd4e 100644
823--- a/src/usr/targeting/common/target.C
824+++ b/src/usr/targeting/common/target.C
825@@ -645,6 +645,53 @@ bool Target::uninstallWriteAttributeCallback()
826 #undef TARG_FN
827 }
828
829+
830+//******************************************************************************
831+// setFrequencyAttributes
832+//******************************************************************************
833+void setFrequencyAttributes(Target * i_sys, uint32_t i_newNestFreq)
834+{
835+
836+ // Calculate the new value for PIB_I2C_NEST_PLL using old freq attributes.
837+ uint32_t l_oldPll = i_sys->getAttr<TARGETING::ATTR_PIB_I2C_NEST_PLL>();
838+ uint32_t l_oldNestFreq = i_sys->getAttr<TARGETING::ATTR_NEST_FREQ_MHZ>();
839+ uint32_t l_newPll = (i_newNestFreq * l_oldPll)/l_oldNestFreq;
840+
841+ //NEST_FREQ
842+ i_sys->setAttr<TARGETING::ATTR_NEST_FREQ_MHZ>(i_newNestFreq);
843+ TRACFCOMP(g_trac_targeting,
844+ "ATTR_NEST_FREQ_MHZ getting set from %d to %d",
845+ l_oldNestFreq,
846+ i_newNestFreq );
847+
848+ //FREQ_X
849+ uint32_t l_freqX = i_newNestFreq * 2;
850+ i_sys->setAttr<TARGETING::ATTR_FREQ_X>(l_freqX);
851+ TRACFCOMP(g_trac_targeting,
852+ "ATTR_FREQ_X getting set to from %d to %d",
853+ l_oldNestFreq*2,
854+ l_freqX );
855+
856+ //FREQ_PB
857+ uint32_t l_freqPb = i_newNestFreq;
858+ i_sys->setAttr<TARGETING::ATTR_FREQ_PB>(l_freqPb);
859+ TRACFCOMP(g_trac_targeting,
860+ "ATTR_FREQ_PB getting set from %d to %d",
861+ l_oldNestFreq,
862+ l_freqPb );
863+
864+ //PIB_I2C_NEST_PLL
865+ i_sys->setAttr<TARGETING::ATTR_PIB_I2C_NEST_PLL>(l_newPll);
866+ TRACFCOMP(g_trac_targeting,
867+ "ATTR_PIB_I2C_NEST_PLL getting set from %x to %x",
868+ l_oldPll,
869+ l_newPll);
870+
871+ return;
872+}
873+
874+
875+
876 //******************************************************************************
877 // Attribute Tanks
878 //******************************************************************************
879diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml
880index 05497fd..88041b4 100644
881--- a/src/usr/targeting/common/xmltohb/attribute_types.xml
882+++ b/src/usr/targeting/common/xmltohb/attribute_types.xml
883@@ -2049,6 +2049,7 @@
884 <simpleType><uint32_t></uint32_t></simpleType>
885 <persistency>non-volatile</persistency>
886 <readable/>
887+ <writeable/>
888 <hwpfToHbAttrMap>
889 <id>ATTR_FREQ_PB</id>
890 <macro>DIRECT</macro>
891@@ -2083,6 +2084,7 @@
892 <simpleType><uint32_t></uint32_t></simpleType>
893 <persistency>non-volatile</persistency>
894 <readable/>
895+ <writeable/>
896 <hwpfToHbAttrMap>
897 <id>ATTR_FREQ_X</id>
898 <macro>DIRECT</macro>
899@@ -6103,7 +6105,7 @@ firmware notes: Used as override attribute for pstate procedure
900 <default>2000</default>
901 </uint32_t>
902 </simpleType>
903- <persistency>volatile</persistency>
904+ <persistency>non-volatile</persistency>
905 <readable/>
906 <writeable/>
907 <hwpfToHbAttrMap>
908@@ -15666,7 +15668,7 @@ firmware notes: Platforms should initialize this attribute to AUTO (0)</descript
909
910 <attribute>
911 <id>MRW_VMEM_REGULATOR_POWER_LIMIT_PER_DIMM_ADJ_ENABLE</id>
912- <description>Machine Readable Workbook enablement of the HWP code to adjust
913+ <description>Machine Readable Workbook enablement of the HWP code to adjust
914 the VMEM regulator power limit based on number of installed DIMMs.
915 </description>
916 <simpleType>
917@@ -15702,7 +15704,7 @@ firmware notes: Platforms should initialize this attribute to AUTO (0)</descript
918
919 <attribute>
920 <id>MRW_VMEM_REGULATOR_MEMORY_POWER_LIMIT_PER_DIMM</id>
921- <description>Machine Readable Workbook VMEM regulator power limit per CDIMM
922+ <description>Machine Readable Workbook VMEM regulator power limit per CDIMM
923 assuming a full configuration. Units in cW.
924 </description>
925 <simpleType>
926@@ -15741,7 +15743,7 @@ firmware notes: Platforms should initialize this attribute to AUTO (0)</descript
927
928 <attribute>
929 <id>MRW_NEST_CAPABLE_FREQUENCIES_SYS</id>
930- <description>The NEST frequencies that the system can support. This is a bit-wise value that represents which of the possible nest frequencies are supported : 2.0GHz, 2.4GHz, or both.
931+ <description>The NEST frequencies that the system can support. This is a bit-wise value that represents which of the possible nest frequencies are supported. : 2.0GHz, 2.4GHz, or both. New frequencies should be added in ascending order.
932 </description>
933 <simpleType>
934 <enumeration>
935--
9361.8.2.2
937