summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Geddes <crgeddes@us.ibm.com>2019-08-26 15:58:17 -0500
committerDaniel M Crowell <dcrowell@us.ibm.com>2019-09-11 10:52:05 -0500
commitbafe5de9d8b538d978d9955386b5f1fd0ae1d82b (patch)
tree958349eb32e7451d9395ecb45db38ed5bc77e624 /src
parent8e9808de50f0115153b3b49703a159f9a915fb10 (diff)
downloadtalos-hostboot-bafe5de9d8b538d978d9955386b5f1fd0ae1d82b.tar.gz
talos-hostboot-bafe5de9d8b538d978d9955386b5f1fd0ae1d82b.zip
Account for Explorer's DMB_REVISION format in its SPD
We have been told that the field we are reading to figure out the EC level of the OCMB via its SPD (offset 0x200) is going to say 0xA0 for the first version of the card, at IBM we would call this EC 0x10. The Explorer manufacture has stated that they will increment the 1st nibble when they do match card revisions, and the 2nd nibble on minor revisions. This commit adds the logic to convert the manufacture's revision format into IBM's EC level format. It also updates the prebuilt cache we use in simics for axone to have the expected 0xA0 value for the explorer SPD stored in the prebuilt cache Change-Id: I10e9523a8fbea847e3124c256fab7bee850cb29d RTC: 214627 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/82873 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Matt Derksen <mderkse1@us.ibm.com> Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/build/citest/etc/eecache_prebuilt2
-rwxr-xr-xsrc/build/citest/etc/workarounds.postsimsetup4
-rwxr-xr-xsrc/build/simics/standalone.simics5
-rw-r--r--src/usr/hwas/hwasPlat.C342
4 files changed, 149 insertions, 204 deletions
diff --git a/src/build/citest/etc/eecache_prebuilt b/src/build/citest/etc/eecache_prebuilt
index d0ac7a63b..6699592b7 100644
--- a/src/build/citest/etc/eecache_prebuilt
+++ b/src/build/citest/etc/eecache_prebuilt
@@ -1 +1 @@
-/gsa/ausgsa/projects/h/hostboot/eecache_prebuilt/06_19_19_eecache_prebuilt.bin.ecc \ No newline at end of file
+/gsa/ausgsa/projects/h/hostboot/eecache_prebuilt/09_06_19_eecache_prebuilt.bin.ecc
diff --git a/src/build/citest/etc/workarounds.postsimsetup b/src/build/citest/etc/workarounds.postsimsetup
index d904f6c3b..f4ca5ebe6 100755
--- a/src/build/citest/etc/workarounds.postsimsetup
+++ b/src/build/citest/etc/workarounds.postsimsetup
@@ -39,5 +39,7 @@ mkdir -p $sb/simu/configs/
grep -v PROC_EC $BACKING_BUILD/src/simu/configs/P9_NIMBUS.config > $sb/simu/configs/P9_NIMBUS.config
echo "SETENV PROC_EC 22" >> $sb/simu/configs/P9_NIMBUS.config
-
+# TODO 215621 remove when simics gets dimmspd.dat updated
+mkdir -p $sb/../simics/import/vpd/
+cp /gsa/ausgsa/projects/h/hostboot/.binary_cache/data/09e225d24bd942a0011ca520311d7cbf289e672e $sb/../simics/import/vpd/dimmspd.dat
##########################################################################
diff --git a/src/build/simics/standalone.simics b/src/build/simics/standalone.simics
index 5d795f96b..4432424bc 100755
--- a/src/build/simics/standalone.simics
+++ b/src/build/simics/standalone.simics
@@ -121,8 +121,9 @@ if ($hb_mode == 1) {
if ($hb_mode == 0) { #Only do this on Axone and later models that have Explorer chip
# IDEC register consumed by Hostboot
- # UCHIP(0x2134)=0x100600D2
- set-class-attr ocmb mscc_regs_xcbi_chip_info 0x100600D2
+ # UCHIP(0x2134)=0x110600D2
+ # TODO RTC: 215621 Remove workarounds after simics gets updated
+ set-class-attr ocmb mscc_regs_xcbi_chip_info 0x110600D2
# Loop over all explorer chips
foreach $obj in (get-object-list ocmb -all){
diff --git a/src/usr/hwas/hwasPlat.C b/src/usr/hwas/hwasPlat.C
index a16d0fdcc..46911bca1 100644
--- a/src/usr/hwas/hwasPlat.C
+++ b/src/usr/hwas/hwasPlat.C
@@ -405,186 +405,65 @@ void ocmbErrlCommit(const TARGETING::TargetHandle_t& i_target,
}
/**
- * @brief This is a small helper function that is used to translate from SPD
- * to OCMB IDEC register values.
+ * @brief This helper function will lookup the chip id and ec levels of
+ * a given OCMB based on what is found in a provided SPD buffer.
+ * The target is passed along for trace information.
*
- * @param[in] i_value The value to translate
+ * @param[in] i_target OCMB target we are looking up IDEC for
*
- * @param[in] i_isID The type of value passed in. Used to search
- * the corresponding map and for FFDC.
+ * @param[in] i_spdBuffer Buffer of at least SPD::OCMB_SPD_EFD_COMBINED_SIZE
+ * bytes of the given OCMB's SPD
*
- * @param[in] i_spdFFDCBytes Byte 1: SPD Module Revision
- * Byte 2: DRAM Interface Type Presented or
- * Emulated
- * Byte 3: Memory Module Interface Type
- * Byte 4: Unused
+ * @param[out] o_chipId Chip Id associated with the given OCMB
+ * (see src/import/chips/common/utils/chipids.H)
*
- * @param[out] o_translatedValue The value resulting from the map.find()
+ * @param[out] o_ec EC level associated with the given OCMB
*
- * @param[in] i_id The SPD ID used to construct the association
- * map. Defaulted to 0xFFFF. This MUST be set
- * when i_isID == false.
- *
- * @return errlHndl_t nullptr on success. Otherwise an error log
- * indicating that the translation failed.
+ * @return nullptr if success, error log otherwise
*
*/
-errlHndl_t ocmbTranslateSpdToIdec(const uint16_t i_value,
- const bool i_isID,
- const uint32_t i_spdFFDCBytes,
- uint16_t& o_translatedValue,
- const uint16_t i_id = 0xFFFF)
+errlHndl_t getOcmbIdecFromSpd(const TARGETING::TargetHandle_t& i_target,
+ uint8_t * i_spdBuffer,
+ uint16_t& o_chipId,
+ uint8_t& o_ec)
{
+ errlHndl_t l_errl = nullptr;
+ // These bytes are used for FFDC and verification purposes.
+ const size_t SPD_REVISION_OFFSET = 1;
+ const size_t DRAM_INTERFACE_TYPE_OFFSET = 2;
+ const size_t MEMORY_MODULE_INTERFACE_TYPE_OFFSET = 3;
- assert((i_isID || (i_id != 0xFFFF)), "i_id must be set to a valid OCMB SPD Chip ID value when attempting to translate an SPD EC value.");
-
- errlHndl_t error = nullptr;
-
- const uint16_t OCMB_ID = i_isID ? i_value : i_id;
-
- const uint32_t GEMINI_EC = 0x0010;
- const uint32_t GEMINI_SPD_EC = 0x0000;
- const uint32_t EXPLORER_EC = 0x0010;
- const uint32_t EXPLORER_SPD_EC = 0x0000;
- // This map will hold the associated values between what is read from
- // the OCMB's IDEC register and the SPD since they use different
- // standards and thus cannot be directly compared.
- std::map<uint32_t, uint32_t> OCMB_ASSOCIATION_MAP;
-
- if (i_isID)
- {
- if (DDIMM_DMB_ID::EXPLORER == OCMB_ID)
- {
- OCMB_ASSOCIATION_MAP[DDIMM_DMB_ID::EXPLORER] =
- POWER_CHIPID::EXPLORER_16;
- }
- else if (DDIMM_DMB_ID::GEMINI == OCMB_ID)
- {
- OCMB_ASSOCIATION_MAP[DDIMM_DMB_ID::GEMINI] =
- POWER_CHIPID::GEMINI_16;
- }
- }
- else
- {
- if (DDIMM_DMB_ID::EXPLORER == OCMB_ID)
- {
- OCMB_ASSOCIATION_MAP[EXPLORER_SPD_EC] = EXPLORER_EC;
- }
- else if (DDIMM_DMB_ID::GEMINI == OCMB_ID)
- {
- OCMB_ASSOCIATION_MAP[GEMINI_SPD_EC] = GEMINI_EC;
- }
- }
-
- auto map_it = OCMB_ASSOCIATION_MAP.find(i_value);
-
- if (map_it == OCMB_ASSOCIATION_MAP.end())
- {
- HWAS_ERR("ocmbTranslateSpdToIdec> Unable to translate "
- "given %s 0x%.4X to a known OCMB IDEC register equivalent",
- i_isID ? "Chip ID" : "Revision",
- i_value);
-
- /*@
- * @errortype
- * @severity ERRL_SEV_PREDICTIVE
- * @moduleid MOD_OCMB_TRANSLATE_SPD_IDEC
- * @reasoncode RC_OCMB_UNEXPECTED_IDEC
- * @userdata1[0:7] SPD Module Revision
- * @userdata1[8:15] DRAM Interface Type Presented or Emulated
- * @userdata1[16:23] Memory Module Interface Type
- * @userdata1[24:31] Unused
- * @userdata1[32:47] The value given to the translate function
- * @userdata1[48:63] 0x1 = value is Chip ID, 0x0 = value is Revision
- * @devdesc The IDEC values read from the OCMB did not
- * appear in the OCMB IDEC to SPD association map.
- * Please update the map with new values.
- * @custdesc Firmware Error
- */
- error = hwasError(ERRORLOG::ERRL_SEV_PREDICTIVE,
- MOD_OCMB_TRANSLATE_SPD_IDEC,
- RC_OCMB_UNEXPECTED_IDEC,
- TWO_UINT32_TO_UINT64(i_spdFFDCBytes,
- TWO_UINT16_TO_UINT32(i_value, i_isID)));
-
- }
- else
- {
- o_translatedValue = map_it->second;
- }
-
- return error;
-}
-
-errlHndl_t ocmbIdecPhase1(const TARGETING::TargetHandle_t& i_target)
-{
- errlHndl_t error = nullptr;
-
- // Allocate buffer to hold SPD and init to 0
- size_t spdBufferSize = SPD::OCMB_SPD_EFD_COMBINED_SIZE;
- uint8_t* spdBuffer = new uint8_t[spdBufferSize];
- memset(spdBuffer, 0, spdBufferSize);
-
- do {
-
- // Read the full SPD.
- error = deviceRead(i_target,
- spdBuffer,
- spdBufferSize,
- DEVICE_SPD_ADDRESS(SPD::ENTIRE_SPD));
-
- // If unable to retrieve the SPD buffer then can't
- // extract the IDEC data, so return error.
- if (error != nullptr)
- {
- HWAS_ERR("ocmbIDEC> Error while trying to read "
- "ENTIRE SPD from 0x%.08X ",
- TARGETING::get_huid(i_target));
- break;
- }
-
- // Make sure we got back the size we were expecting.
- assert(spdBufferSize == SPD::OCMB_SPD_EFD_COMBINED_SIZE,
- "ocmbIDEC> OCMB SPD read size %d "
- "doesn't match the expected size %d",
- spdBufferSize,
- SPD::OCMB_SPD_EFD_COMBINED_SIZE);
-
- // These bytes are used for FFDC and verification purposes.
- const size_t SPD_REVISION_OFFSET = 1;
- const size_t DRAM_INTERFACE_TYPE_OFFSET = 2;
- const size_t MEMORY_MODULE_INTERFACE_TYPE_OFFSET = 3;
+ // This is the value that signifies the SPD we read is for a DDIMM.
+ const uint8_t DDIMM_MEMORY_INTERFACE_TYPE = 0x0A;
- // This is the value that signifies the SPD we read is for a DDIMM.
- const uint32_t DDIMM_MEMORY_INTERFACE_TYPE = 0x0A;
+ const uint8_t l_spdModuleRevision =
+ *(i_spdBuffer + SPD_REVISION_OFFSET);
- const uint8_t spdModuleRevision =
- *(spdBuffer + SPD_REVISION_OFFSET);
+ const uint8_t l_spdDRAMInterfaceType =
+ *(i_spdBuffer + DRAM_INTERFACE_TYPE_OFFSET);
- const uint8_t spdDRAMInterfaceType =
- *(spdBuffer + DRAM_INTERFACE_TYPE_OFFSET);
+ const uint8_t l_spdMemoryInterfaceType =
+ *(i_spdBuffer + MEMORY_MODULE_INTERFACE_TYPE_OFFSET);
- const uint8_t spdMemoryInterfaceType =
- *(spdBuffer + MEMORY_MODULE_INTERFACE_TYPE_OFFSET);
+ // Byte 1 SPD Module Revision
+ // Byte 2 DRAM Interface Type Presented or Emulated
+ // Byte 3 Memory Module Interface Type
+ const uint32_t SPD_FFDC_BYTES = TWO_UINT16_TO_UINT32(
+ TWO_UINT8_TO_UINT16(l_spdModuleRevision, l_spdDRAMInterfaceType),
+ TWO_UINT8_TO_UINT16(l_spdMemoryInterfaceType, 0));
- // Byte 1 SPD Module Revision
- // Byte 2 DRAM Interface Type Presented or Emulated
- // Byte 3 Memory Module Interface Type
- const uint32_t SPD_FFDC_BYTES = TWO_UINT16_TO_UINT32(
- TWO_UINT8_TO_UINT16(spdModuleRevision, spdDRAMInterfaceType),
- TWO_UINT8_TO_UINT16(spdMemoryInterfaceType, 0));
+ do{
// Since the byte offsets used to get the IDEC info out of the SPD are
// specific to the DDIMM interface type we must first verify that we
// read from an SPD of that type.
- if (DDIMM_MEMORY_INTERFACE_TYPE != spdMemoryInterfaceType)
+ if (DDIMM_MEMORY_INTERFACE_TYPE != l_spdMemoryInterfaceType)
{
- HWAS_ERR("ocmbIDEC> OCMB 0x%.8X memory module interface type "
- "didn't match the expected type. "
- "Expected 0x%.2X, Actual 0x%.2X",
- TARGETING::get_huid(i_target),
- DDIMM_MEMORY_INTERFACE_TYPE,
- spdMemoryInterfaceType);
+ HWAS_ERR("getOcmbIdecFromSpd> memory module interface type "
+ "didn't match the expected type. "
+ "Expected 0x%.2X, Actual 0x%.2X",
+ DDIMM_MEMORY_INTERFACE_TYPE,
+ l_spdMemoryInterfaceType);
/*@
* @errortype
@@ -603,17 +482,17 @@ errlHndl_t ocmbIdecPhase1(const TARGETING::TargetHandle_t& i_target)
* continue.
* @custdesc Invalid or unsupported memory card installed.
*/
- error = hwasError(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ l_errl = hwasError(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
MOD_OCMB_IDEC,
RC_OCMB_INTERFACE_TYPE_MISMATCH,
TWO_UINT32_TO_UINT64(SPD_FFDC_BYTES,
DDIMM_MEMORY_INTERFACE_TYPE),
TARGETING::get_huid(i_target));
- error->addProcedureCallout(EPUB_PRC_HB_CODE,
- SRCI_PRIORITY_LOW);
+ l_errl->addProcedureCallout(EPUB_PRC_HB_CODE,
+ SRCI_PRIORITY_LOW);
- error->addHwCallout(i_target,
+ l_errl->addHwCallout(i_target,
SRCI_PRIORITY_HIGH,
NO_DECONFIG,
GARD_NULL);
@@ -625,37 +504,59 @@ errlHndl_t ocmbIdecPhase1(const TARGETING::TargetHandle_t& i_target)
// SPD IDEC info is in the following three bytes
const size_t SPD_ID_LEAST_SIGNIFICANT_BYTE_OFFSET = 198;
const size_t SPD_ID_MOST_SIGNIFICANT_BYTE_OFFSET = 199;
- const size_t SPD_EC_OFFSET = 200;
+ const size_t DMB_REV_OFFSET = 200;
// Get the ID from the SPD and verify that it matches what we read from
// the IDEC register.
- uint16_t spdId = TWO_UINT8_TO_UINT16(
- *(spdBuffer + SPD_ID_LEAST_SIGNIFICANT_BYTE_OFFSET),
- *(spdBuffer + SPD_ID_MOST_SIGNIFICANT_BYTE_OFFSET));
+ uint16_t l_spdId = TWO_UINT8_TO_UINT16(
+ *(i_spdBuffer + SPD_ID_LEAST_SIGNIFICANT_BYTE_OFFSET),
+ *(i_spdBuffer + SPD_ID_MOST_SIGNIFICANT_BYTE_OFFSET));
- uint8_t spdEc = *(spdBuffer + SPD_EC_OFFSET);
+ // Bytes 200 of the SPD contains the DMB Revision, this is essentially the
+ // OCMB manufacture's version of the chip. The manufacture can define any
+ // format for this field and we must add special logic to convert the
+ // manufacture's DMB_REV to the EC level IBM is familiar with.
+ uint8_t l_spdDmbRev = *(i_spdBuffer + DMB_REV_OFFSET);
- if (DDIMM_DMB_ID::EXPLORER == spdId)
+ HWAS_INF("getOcmbIdecFromSpd> OCMB 0x%.8x l_spdId = 0x%.4X l_spdDmbRev = 0x%.2x",
+ TARGETING::get_huid(i_target), l_spdId, l_spdDmbRev);
+
+ if (DDIMM_DMB_ID::EXPLORER == l_spdId)
{
- HWAS_INF("ocmbIdecPhase1> OCMB 0x%.8X chip type is EXPLORER",
- TARGETING::get_huid(i_target));
+ o_chipId = POWER_CHIPID::EXPLORER_16;
+ // Must convert Explorer's versioning into IBM-style EC levels.
+ // Explorer vendor has stated versioning will start at 0xA0 and increment
+ // 1st nibble for major revisions and 2nd nibble by 1 for minor revisions
+ // Examples :
+ // Version 0xA0 = EC 0x10
+ // Version 0xA1 = EC 0x11
+ // Version 0xB2 = EC 0x22
+
+ // Resulting formula from pattern in examples above is as follows:
+ o_ec = (l_spdDmbRev - 0x90);
}
- else if (DDIMM_DMB_ID::GEMINI == spdId)
+ else if (DDIMM_DMB_ID::GEMINI == l_spdId)
{
- HWAS_INF("ocmbIdecPhase1> OCMB 0x%.8X chip type is GEMINI",
- TARGETING::get_huid(i_target));
+ o_chipId = POWER_CHIPID::GEMINI_16;
+
+ HWAS_ASSERT(l_spdDmbRev == 0x0,
+ "Invalid Gemini DMB Revision Number, expected to find 0x0 at byte 200 in Gemini SPD");
+
+ // 0x10 is the only valid EC level for Gemini cards. If we find 0x0 @ byte 200 in
+ // the Gemini SPD then we will return 0x10 as the EC level
+ o_ec = 0x10;
}
else
{
- HWAS_ERR("ocmbIdecPhase1> Unknown OCMB chip type discovered in SPD "
- "ID=0x%.4X OCMB HUID 0x%.8X",
- spdId,
- TARGETING::get_huid(i_target));
+ HWAS_ERR("getOcmbIdecFromSpd> Unknown OCMB chip type discovered in SPD "
+ "ID=0x%.4X OCMB HUID 0x%.8x",
+ l_spdId,
+ TARGETING::get_huid(i_target));
/*@
* @errortype
* @severity ERRL_SEV_PREDICTIVE
- * @moduleid MOD_OCMB_IDEC_PHASE_1
+ * @moduleid MOD_OCMB_IDEC
* @reasoncode RC_OCMB_UNKNOWN_CHIP_TYPE
* @userdata1[0:7] SPD Module Revision
* @userdata1[8:15] DRAM Interface Type Presented or Emulated
@@ -667,46 +568,87 @@ errlHndl_t ocmbIdecPhase1(const TARGETING::TargetHandle_t& i_target)
* OCMB chip types.
* @custdesc Unsupported memory installed.
*/
- error = hwasError(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ l_errl = hwasError(ERRORLOG::ERRL_SEV_PREDICTIVE,
MOD_OCMB_IDEC_PHASE_1,
RC_OCMB_UNKNOWN_CHIP_TYPE,
- TWO_UINT32_TO_UINT64(SPD_FFDC_BYTES, spdId),
+ TWO_UINT32_TO_UINT64(SPD_FFDC_BYTES, l_spdId),
TARGETING::get_huid(i_target));
- // Add callouts and commit
- ocmbErrlCommit(i_target, error);
-
break;
}
- uint16_t id = 0;
- uint16_t ec = 0;
- bool isId = true;
+ }while(0);
+
+ return l_errl;
+
+}
+
+
+errlHndl_t ocmbIdecPhase1(const TARGETING::TargetHandle_t& i_target)
+{
+ errlHndl_t l_errl = nullptr;
+
+ // Allocate buffer to hold SPD and init to 0
+ size_t l_spdBufferSize = SPD::OCMB_SPD_EFD_COMBINED_SIZE;
+ uint8_t* l_spdBuffer = new uint8_t[l_spdBufferSize];
+ memset(l_spdBuffer, 0, l_spdBufferSize);
+ uint16_t l_chipId = 0;
+ uint8_t l_chipEc = 0;
+ do {
- error = ocmbTranslateSpdToIdec(spdId, isId, SPD_FFDC_BYTES, id);
- if (error)
+ // Read the full SPD.
+ l_errl = deviceRead(i_target,
+ l_spdBuffer,
+ l_spdBufferSize,
+ DEVICE_SPD_ADDRESS(SPD::ENTIRE_SPD));
+
+ // If unable to retrieve the SPD buffer then can't
+ // extract the IDEC data, so return error.
+ if (l_errl != nullptr)
{
- ocmbErrlCommit(i_target, error);
+ HWAS_ERR("ocmbIdecPhase1> Error while trying to read "
+ "ENTIRE SPD from 0x%.08X ",
+ TARGETING::get_huid(i_target));
+ break;
}
- error = ocmbTranslateSpdToIdec(spdEc, !isId, SPD_FFDC_BYTES, ec, spdId);
- if (error)
+ // Make sure we got back the size we were expecting.
+ assert(l_spdBufferSize == SPD::OCMB_SPD_EFD_COMBINED_SIZE,
+ "ocmbIdecPhase1> OCMB SPD read size %d "
+ "doesn't match the expected size %d",
+ l_spdBufferSize,
+ SPD::OCMB_SPD_EFD_COMBINED_SIZE);
+
+ l_errl = getOcmbIdecFromSpd(i_target,
+ l_spdBuffer,
+ l_chipId,
+ l_chipEc);
+
+ // If we were unable to read the IDEC information from the SPD
+ // then break out early and do not set the associated attributes
+ if (l_errl != nullptr)
{
- ocmbErrlCommit(i_target, error);
+ HWAS_ERR("ocmbIdecPhase1> Error while trying to parse "
+ "chip id and ec values from SPD read from OCMB 0x%.08X ",
+ TARGETING::get_huid(i_target));
+ break;
}
+ HWAS_INF("ocmbIdecPhase1> Read Chip ID = 0x%x Chip EC = 0x%x from target 0x%.08X",
+ l_chipId, l_chipEc, TARGETING::get_huid(i_target) );
+
// set the explorer chip EC attributes.
- i_target->setAttr<TARGETING::ATTR_EC>(ec);
- i_target->setAttr<TARGETING::ATTR_HDAT_EC>(ec);
+ i_target->setAttr<TARGETING::ATTR_EC>(l_chipEc);
+ i_target->setAttr<TARGETING::ATTR_HDAT_EC>(l_chipEc);
// set the explorer chip id attribute.
- i_target->setAttr<TARGETING::ATTR_CHIP_ID>(id);
+ i_target->setAttr<TARGETING::ATTR_CHIP_ID>(l_chipId);
} while(0);
- delete[] spdBuffer;
- return error;
+ delete[] l_spdBuffer;
+ return l_errl;
}
OpenPOWER on IntegriCloud