summaryrefslogtreecommitdiffstats
path: root/src/usr/isteps/nvdimm/nvdimm_update.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/isteps/nvdimm/nvdimm_update.C')
-rw-r--r--src/usr/isteps/nvdimm/nvdimm_update.C687
1 files changed, 589 insertions, 98 deletions
diff --git a/src/usr/isteps/nvdimm/nvdimm_update.C b/src/usr/isteps/nvdimm/nvdimm_update.C
index 2e1f61c8c..6075a660f 100644
--- a/src/usr/isteps/nvdimm/nvdimm_update.C
+++ b/src/usr/isteps/nvdimm/nvdimm_update.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018,2019 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -26,6 +26,7 @@
#include "nvdimm.H"
#include <isteps/nvdimm/nvdimm.H>
#include <isteps/nvdimm/nvdimmreasoncodes.H>
+#include "bpm_update.H"
#include <initservice/istepdispatcherif.H> // sendProgressCode
#include <util/utilmclmgr.H> // secure LID manager
@@ -33,6 +34,7 @@
#include <devicefw/userif.H>
#include <vpd/spdenums.H>
#include <sys/time.h>
+#include <vector>
// Unique tracing for nvdimm update process
const char NVDIMM_UPD[] = "NVDIMM_UPD";
@@ -41,7 +43,7 @@ TRAC_INIT(&g_trac_nvdimm_upd, NVDIMM_UPD, 2*KILOBYTE);
// Easy macro replace for unit testing
-// #define TRACUCOMP(args...) TRACFCOMP(args)
+//#define TRACUCOMP(args...) TRACFCOMP(args)
#define TRACUCOMP(args...)
namespace NVDIMM
@@ -144,8 +146,10 @@ typedef union {
} nvdimm_cmd_status0_t;
// A code update block is composed of this many bytes
-const uint8_t BYTES_PER_BLOCK = 32;
+constexpr uint8_t BYTES_PER_BLOCK = 32;
+// Maximum allowed region write retries
+constexpr uint8_t MAX_REGION_WRITE_RETRY_ATTEMPTS = 3;
///////////////////////////////////////////////////////////////////////////////
// NVDIMM LID Image
@@ -182,6 +186,7 @@ uint16_t NvdimmLidImage::getVersion()
return o_version;
}
+
const uint8_t * NvdimmLidImage::getHeaderAndSmartSignature(uint16_t & o_size)
{
o_size = 0;
@@ -264,7 +269,10 @@ NvdimmInstalledImage::NvdimmInstalledImage(TARGETING::Target * i_nvDimm) :
iv_dimm(i_nvDimm), iv_version(INVALID_VERSION),
iv_manufacturer_id(INVALID_ID), iv_product_id(INVALID_ID),
iv_timeout(INVALID_TIMEOUT),
- iv_max_blocks_per_region(INVALID_REGION_BLOCK_SIZE)
+ iv_max_blocks_per_region(INVALID_REGION_BLOCK_SIZE),
+ iv_fw_update_mode_enabled(false),
+ iv_region_write_retries(0),
+ iv_blockSizeSupported(INVALID_BLOCK_SIZE)
{
// initialize to invalid values
}
@@ -350,12 +358,50 @@ errlHndl_t NvdimmInstalledImage::getVersion(uint16_t & o_version,
return l_err;
}
+errlHndl_t NvdimmInstalledImage::getBlockWriteSizeSupported(uint64_t & o_blockSize)
+{
+ errlHndl_t l_err = nullptr;
+
+ do {
+ if (iv_blockSizeSupported == INVALID_BLOCK_SIZE)
+ {
+ uint16_t version = INVALID_VERSION;
+ l_err = getVersion(version, 0);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"getBlockWriteSizeSupported: "
+ "Failed to get version for 0x%.8X NVDIMM",
+ TARGETING::get_huid(iv_dimm));
+ break;
+ }
+
+ // The block write is more prone to random system interrupt
+ // which does something funny to the i2c bus.
+ // v3.A has the timeout increased to mitigate that
+ if (version >= 0x3A00)
+ {
+ // version supports 32-byte block size
+ iv_blockSizeSupported = 32;
+ }
+ else
+ {
+ // default to word size max write
+ iv_blockSizeSupported = sizeof(uint16_t);
+ }
+ TRACFCOMP( g_trac_nvdimm_upd, ERR_MRK"getBlockWriteSizeSupported: "
+ "block size %d supported for 0x%.8X NVDIMM (version 0x%04X)",
+ iv_blockSizeSupported, TARGETING::get_huid(iv_dimm),
+ version );
+ }
+ } while (0);
+ o_blockSize = iv_blockSizeSupported;
+ return l_err;
+}
errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
{
errlHndl_t l_err = nullptr;
- // need to always disable this after it gets enabled
- bool l_fw_update_mode_enabled = false;
+
do {
INITSERVICE::sendProgressCode();
////////////////////////////////////////////////////////////////////////
@@ -381,7 +427,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
TRACFCOMP(g_trac_nvdimm_upd,ERR_MRK"updateImage: "
"NV controller is busy (0x%08X) for NVDIMM 0x%.8X",
l_status.whole, TARGETING::get_huid(iv_dimm));
- /*
+ /*@
*@errortype
*@moduleid UPDATE_IMAGE
*@reasoncode NVDIMM_OPERATION_IN_PROGRESS
@@ -398,11 +444,14 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
l_status.whole,
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace( NVDIMM_COMP_NAME, 256 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
l_err->addPartCallout( iv_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
break;
}
@@ -427,8 +476,6 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
TARGETING::get_huid(iv_dimm));
break;
}
- // Set this flag so we will disable the update mode on error
- l_fw_update_mode_enabled = true;
// 5. Clear the Firmware Operation status
TRACUCOMP(g_trac_nvdimm_upd, "updateImage: step 5");
@@ -549,7 +596,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
"NVDIMM 0x%.8X: data checksums mismatch (calc host: 0x%X "
"and nv: 0x%X) for first part (header + SMART signature)",
TARGETING::get_huid(iv_dimm), hostCksm, nvCksm);
- /*
+ /*@
*@errortype
*@moduleid UPDATE_IMAGE
*@reasoncode NVDIMM_CHECKSUM_ERROR
@@ -571,6 +618,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
0x0000),
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace( NVDIMM_COMP_NAME, 256 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
// maybe some data was altered on the NV controller
l_err->addPartCallout( iv_dimm,
@@ -579,6 +627,8 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
// possible code issue
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
break;
}
@@ -641,7 +691,6 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
// 12. Disable firmware update mode
TRACUCOMP(g_trac_nvdimm_upd, "updateImage: step 12");
- l_fw_update_mode_enabled = false; // don't retry the disable on error
l_err = changeFwUpdateMode(FW_UPDATE_MODE_DISABLED);
if (l_err)
{
@@ -668,7 +717,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
// Reset controller to activate new firmware
TRACUCOMP(g_trac_nvdimm_upd, "updateImage: resetController");
- l_err = resetController();
+ l_err = nvdimmResetController(iv_dimm);
if (l_err)
{
TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK "updateImage: "
@@ -701,7 +750,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage)
} while (0);
// If update operation is aborted, we need to disable update mode
- if (l_fw_update_mode_enabled)
+ if (iv_fw_update_mode_enabled)
{
TRACFCOMP(g_trac_nvdimm_upd, "updateImage: update was aborted, so disable FW_UPDATE_MODE");
errlHndl_t l_err2 = changeFwUpdateMode(FW_UPDATE_MODE_DISABLED);
@@ -765,7 +814,7 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage)
}
if (fw_img_total_regions == 0)
{
- /*
+ /*@
*@errortype
*@moduleid UPDATE_IMAGE_DATA
*@reasoncode NVDIMM_ZERO_TOTAL_REGIONS
@@ -787,6 +836,8 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage)
0x00000000),
ERRORLOG::ErrlEntry::ADD_SW_CALLOUT );
l_err->collectTrace( NVDIMM_COMP_NAME, 256 );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
break;
}
@@ -812,11 +863,15 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage)
break;
}
+ uint8_t l_region_write_retries = 0; // local region write retry count
uint16_t region = 0;
while (region < fw_img_total_regions)
{
- if (region % 10 == 0)
+ if (region % 100 == 0)
{
+ TRACFCOMP(g_trac_nvdimm_upd,
+ "updateImage: progress code for sending region %d",
+ region);
INITSERVICE::sendProgressCode();
}
TRACUCOMP(g_trac_nvdimm_upd, "updateImage: step 10.a - region 0x%04X",
@@ -914,15 +969,17 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage)
if (hostCksm != nvCksm)
{
TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"updateImageData: "
- "Region %d of NVDIMM 0x%.8X: data checksums mismatch "
+ "Region %d out of %d on NVDIMM 0x%.8X: data checksums mismatch "
"(calc host: 0x%X and nv: 0x%X)",
- region, TARGETING::get_huid(iv_dimm), hostCksm, nvCksm);
+ region, fw_img_total_regions,
+ TARGETING::get_huid(iv_dimm), hostCksm, nvCksm);
- /*
+ /*@
*@errortype
*@moduleid UPDATE_IMAGE_DATA
*@reasoncode NVDIMM_CHECKSUM_ERROR
- *@userdata1 NVDIMM Target Huid
+ *@userdata1[0:31] NVDIMM Target Huid
+ *@userdata1[32:63] Retry count for this region
*@userdata2[0:15] Host checksum calculated
*@userdata2[16:31] NV checksum returned
*@userdata2[32:47] size of data for checksum
@@ -934,18 +991,44 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage)
ERRORLOG::ERRL_SEV_PREDICTIVE,
UPDATE_IMAGE_DATA,
NVDIMM_CHECKSUM_ERROR,
- TARGETING::get_huid(iv_dimm),
+ TWO_UINT32_TO_UINT64(
+ TARGETING::get_huid(iv_dimm),
+ l_region_write_retries),
FOUR_UINT16_TO_UINT64(
hostCksm, nvCksm,
region, data_len),
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
- l_err->collectTrace( NVDIMM_COMP_NAME, 256 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
l_err->addPartCallout( iv_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
+
+ // Under the total retry attempts per region?
+ if (l_region_write_retries < MAX_REGION_WRITE_RETRY_ATTEMPTS)
+ {
+ TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"updateImageData: "
+ "Region %d on NVDIMM 0x%.8X failed, retry %d",
+ region, TARGETING::get_huid(iv_dimm),l_region_write_retries);
+ l_err->collectTrace(NVDIMM_UPD, 512);
+
+ // Change PREDICTIVE to INFORMATIONAL as this might be recoverable
+ l_err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL);
+
+ // Commit this log and retry region write
+ ERRORLOG::errlCommit(l_err, NVDIMM_COMP_ID);
+ l_err = nullptr;
+
+ // Update total for this region
+ l_region_write_retries++;
+ // update total retries for entire NVDIMM
+ iv_region_write_retries++;
+ continue;
+ }
break;
}
@@ -989,7 +1072,7 @@ errlHndl_t NvdimmInstalledImage::changeFwUpdateMode(fw_update_mode i_mode)
((i_mode == FW_UPDATE_MODE_DISABLED) &&
(opStatus.fw_ops_update_mode == 0))) )
{
- /*
+ /*@
*@errortype
*@moduleid CHANGE_FW_UPDATE_MODE
*@reasoncode NVDIMM_UPDATE_MODE_UNCHANGED
@@ -1009,11 +1092,25 @@ errlHndl_t NvdimmInstalledImage::changeFwUpdateMode(fw_update_mode i_mode)
0x00, 0x00),
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace( NVDIMM_COMP_NAME, 256 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
l_err->addPartCallout( iv_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
+ }
+ else
+ {
+ if (opStatus.fw_ops_update_mode == 1)
+ {
+ iv_fw_update_mode_enabled = true;
+ }
+ else
+ {
+ iv_fw_update_mode_enabled = false;
+ }
}
}
}
@@ -1025,8 +1122,9 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsBlockReceived()
{
errlHndl_t l_err = nullptr;
- // retry for a total of 100ms
- uint32_t timeout_ms_val = 100;
+ // retry for a total of 500ms
+ const uint32_t MAX_WAIT_FOR_OPS_BLOCK_RECEIVED = 500;
+ uint32_t timeout_ms_val = MAX_WAIT_FOR_OPS_BLOCK_RECEIVED;
bool blockReceived = false;
fw_ops_status_t opStatus;
@@ -1042,6 +1140,7 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsBlockReceived()
TARGETING::get_huid(iv_dimm), timeout_ms_val);
break;
}
+
if (!opStatus.fw_ops_block_received)
{
// wait 1 millisecond between checking status
@@ -1066,7 +1165,13 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsBlockReceived()
if (!blockReceived && !l_err)
{
- /*
+ TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"waitFwOpsBlockReceived: "
+ "NVDIMM 0x%.8X FIRMWARE_OPS_STATUS (timeout: %d ms) "
+ "-- Last status: 0x%02X",
+ TARGETING::get_huid(iv_dimm), MAX_WAIT_FOR_OPS_BLOCK_RECEIVED,
+ opStatus.whole);
+
+ /*@
*@errortype
*@moduleid WAIT_FW_OPS_BLOCK_RECEIVED
*@reasoncode NVDIMM_BLOCK_NOT_RECEIVED
@@ -1086,16 +1191,19 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsBlockReceived()
(
TWO_UINT8_TO_UINT16( 0x00,
opStatus.whole),
- 100,
+ MAX_WAIT_FOR_OPS_BLOCK_RECEIVED,
timeout_ms_val
),
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace(NVDIMM_COMP_NAME, 512 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
l_err->addPartCallout( iv_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
}
return l_err;
@@ -1145,7 +1253,7 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsComplete()
if (!opsComplete && !l_err)
{
- /*
+ /*@
*@errortype
*@moduleid WAIT_FW_OPS_COMPLETE
*@reasoncode NVDIMM_FW_OPS_IN_PROGRESS_TIMEOUT
@@ -1169,11 +1277,14 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsComplete()
),
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
l_err->addPartCallout( iv_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
}
}
return l_err;
@@ -1234,6 +1345,103 @@ errlHndl_t NvdimmInstalledImage::clearFwOpsStatus()
"NVDIMM 0x%.8X clear FIRMWARE_OPS_STATUS register failed",
TARGETING::get_huid(iv_dimm));
}
+ else
+ {
+ // Verify expected bits cleared
+
+ // Setup expected cleared status byte
+ fw_ops_status_t l_cleared_ops_status;
+ l_cleared_ops_status.whole = 0x00;
+ if (iv_fw_update_mode_enabled)
+ {
+ // set BIT 2 -- this should not be cleared by the command
+ l_cleared_ops_status.fw_ops_update_mode = 1;
+ }
+
+ // Set some timeout so this doesn't cause endless loop
+ uint16_t timeout_val = INVALID_TIMEOUT;
+ l_err = getFwOpsTimeout(timeout_val);
+ // Note: potential error will just exit the while loop and be returned
+
+ // convert seconds to ms value
+ // double the timeout to ensure enough time has elapsed for the clear
+ // note: doubling here instead of just doubling timeout_val since that
+ // variable is only a bit16 vs bit32
+ uint32_t timeout_ms_val = timeout_val * 1000 * 2;
+
+ fw_ops_status_t l_ops_status;
+
+ while (!l_err)
+ {
+ l_err = nvdimmReadReg(iv_dimm, FIRMWARE_OPS_STATUS, l_ops_status.whole);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"clearFwOpsStatus: "
+ "NVDIMM 0x%.8X read FIRMWARE_OPS_STATUS register failed "
+ " (0x%02X)",
+ TARGETING::get_huid(iv_dimm), l_ops_status.whole);
+ break;
+ }
+
+ // Exit if expected cleared status is found
+ if (l_ops_status.whole == l_cleared_ops_status.whole)
+ {
+ break;
+ }
+
+ // wait 1 millisecond between checking status
+ if (timeout_ms_val > 0)
+ {
+ timeout_ms_val -= 1;
+ nanosleep(0, NS_PER_MSEC);
+ }
+ else
+ {
+ // timeout hit
+ TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"clearFwOpsStatus: "
+ "NVDIMM 0x%.8X FIRMWARE_OPS_STATUS register reads 0x%02X "
+ "instead of cleared value of 0x%02X after %lld seconds",
+ TARGETING::get_huid(iv_dimm), l_ops_status.whole,
+ l_cleared_ops_status.whole, timeout_val*2);
+
+ /*@
+ *@errortype
+ *@moduleid CLEAR_FW_OPS_STATUS
+ *@reasoncode NVDIMM_CLEAR_FW_OPS_STATUS_TIMEOUT
+ *@userdata1 NVDIMM Target Huid
+ *@userdata2[0:7] Last FIRMWARE_OPS_STATUS read
+ *@userdata2[8:15] Expected cleared status
+ *@userdata2[16:31] Reserved
+ *@userdata2[32:63] Timeout (seconds)
+ *@devdesc FIRMWARE_OPS_STATUS not cleared
+ *@custdesc NVDIMM not updated
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_PREDICTIVE,
+ CLEAR_FW_OPS_STATUS,
+ NVDIMM_CLEAR_FW_OPS_STATUS_TIMEOUT,
+ TARGETING::get_huid(iv_dimm),
+ TWO_UINT16_ONE_UINT32_TO_UINT64
+ (
+ TWO_UINT8_TO_UINT16(
+ l_ops_status.whole,
+ l_cleared_ops_status.whole),
+ 0x0000,
+ timeout_val * 2
+ ),
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+ l_err->collectTrace(NVDIMM_COMP_NAME, 256);
+ l_err->addPartCallout( iv_dimm,
+ HWAS::NV_CONTROLLER_PART_TYPE,
+ HWAS::SRCI_PRIORITY_HIGH );
+ l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_LOW );
+
+ break;
+ }
+ } // end of while (!l_err) loop
+ } // end of Verify expected bits cleared
+
return l_err;
}
@@ -1317,7 +1525,7 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data,
}
if (blocks_per_region > max_blocks_per_region)
{
- /*
+ /*@
*@errortype
*@moduleid BYTE_REGION_BLOCK_TRANSFER
*@reasoncode NVDIMM_DATA_SIZE_TOO_LARGE
@@ -1352,7 +1560,7 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data,
if (i_data_size > (BYTES_PER_BLOCK*blocks_per_region))
{
- /*
+ /*@
*@errortype
*@moduleid BYTE_REGION_BLOCK_TRANSFER
*@reasoncode NVDIMM_DATA_SIZE_INVALID
@@ -1421,15 +1629,29 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data,
TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: "
"Unable to open page for BLOCK %d transfer of NVDIMM "
"0x%.8X", blockNum, TARGETING::get_huid(iv_dimm));
+ break;
}
size_t l_numBytes = BYTES_PER_BLOCK;
uint8_t l_reg_addr = ADDRESS(TYPED_BLOCK_DATA_BYTE0);
+
+ // Grab whether word or 32-byte block write is supported
+ uint64_t blockSizeSupported = INVALID_BLOCK_SIZE;
+ l_err = getBlockWriteSizeSupported(blockSizeSupported);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: "
+ "Unable to grab maximum block write size for NVDIMM 0x%.8X",
+ TARGETING::get_huid(iv_dimm));
+ break;
+ }
+
l_err = DeviceFW::deviceOp( DeviceFW::WRITE,
iv_dimm,
pCurrentBlockData,
l_numBytes,
- DEVICE_NVDIMM_ADDRESS(l_reg_addr) );
+ DEVICE_NVDIMM_RAW_ADDRESS_WITH_BLOCKSIZE(l_reg_addr, blockSizeSupported)
+ );
if (l_err)
{
TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: "
@@ -1437,8 +1659,6 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data,
blockNum, l_reg_addr, TARGETING::get_huid(iv_dimm));
break;
}
- // increment to next block
- pCurrentBlockData += BYTES_PER_BLOCK;
// After a block has been transferred, verify that the 32-byte block
// was received by polling FIRMWARE_OPS_STATUS offset for
@@ -1449,10 +1669,39 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data,
TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: "
"Block %d read of FIRMWARE_OPS_STATUS failed on NVDIMM "
" 0x%.8X", blockNum, TARGETING::get_huid(iv_dimm));
+
+ size_t tmpNumBytes = l_numBytes;
+ uint8_t tmpBuffer[tmpNumBytes];
+ errlHndl_t l_err2 = DeviceFW::deviceOp( DeviceFW::READ,
+ iv_dimm,
+ tmpBuffer,
+ tmpNumBytes,
+ DEVICE_NVDIMM_ADDRESS(l_reg_addr) );
+ if (l_err2)
+ {
+ TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: "
+ "Block %d read from 0x%02X failed on NVDIMM 0x%.8X",
+ blockNum, l_reg_addr, TARGETING::get_huid(iv_dimm));
+ l_err2->plid(l_err->plid());
+ l_err2->collectTrace(NVDIMM_COMP_NAME);
+ l_err2->collectTrace(NVDIMM_UPD);
+ errlCommit(l_err2, NVDIMM_COMP_ID);
+ break;
+ }
+ else
+ {
+ TRACFBIN(g_trac_nvdimm_upd, "byteRegionBlockTransfer: Wrote block", pCurrentBlockData, l_numBytes);
+ TRACFBIN(g_trac_nvdimm_upd, "byteRegionBlockTransfer: Read-back block", tmpBuffer, l_numBytes);
+ }
+
break;
}
+
// block of data successfully sent to NV controller
TRACUCOMP(g_trac_nvdimm_upd,"byteRegionBlockTransfer: block 0x%02X successfully sent to NV controller", blockNum);
+
+ // increment to next block
+ pCurrentBlockData += BYTES_PER_BLOCK;
blockNum++;
}
@@ -1516,7 +1765,7 @@ errlHndl_t NvdimmInstalledImage::validateFwHeader()
l_err = isFwOpsSuccess(opsSuccessful);
if (!l_err && !opsSuccessful)
{
- /*
+ /*@
*@errortype
*@moduleid VALIDATE_FW_HEADER
*@reasoncode NVDIMM_FW_OPS_NOT_SUCCESSFUL
@@ -1533,11 +1782,14 @@ errlHndl_t NvdimmInstalledImage::validateFwHeader()
opsCmd.whole,
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
l_err->addPartCallout( iv_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
}
}
}
@@ -1565,7 +1817,7 @@ errlHndl_t NvdimmInstalledImage::commitFwRegion()
l_err = isFwOpsSuccess(opsSuccessful);
if (!l_err && !opsSuccessful)
{
- /*
+ /*@
*@errortype
*@moduleid COMMIT_FW_REGION
*@reasoncode NVDIMM_FW_OPS_NOT_SUCCESSFUL
@@ -1582,11 +1834,14 @@ errlHndl_t NvdimmInstalledImage::commitFwRegion()
opsCmd.whole,
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
l_err->addPartCallout( iv_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
}
}
}
@@ -1615,7 +1870,7 @@ errlHndl_t NvdimmInstalledImage::clearFwDataBlock()
l_err = isFwOpsSuccess(ops_success);
if (!l_err && !ops_success)
{
- /*
+ /*@
*@errortype
*@moduleid CLEAR_FW_DATA_BLOCK
*@reasoncode NVDIMM_FW_OPS_NOT_SUCCESSFUL
@@ -1632,11 +1887,14 @@ errlHndl_t NvdimmInstalledImage::clearFwDataBlock()
opsCmd.whole,
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
l_err->addPartCallout( iv_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
}
}
}
@@ -1664,7 +1922,7 @@ errlHndl_t NvdimmInstalledImage::validateFwImage()
// create an error if operation not successful
if (!l_err && !opsSuccessful)
{
- /*
+ /*@
*@errortype
*@moduleid VALIDATE_FW_IMAGE
*@reasoncode NVDIMM_FW_OPS_NOT_SUCCESSFUL
@@ -1681,12 +1939,14 @@ errlHndl_t NvdimmInstalledImage::validateFwImage()
opsCmd.whole,
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ nvdimmAddVendorLog(iv_dimm, l_err);
l_err->addPartCallout( iv_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
-
+ nvdimmAddPage4Regs(iv_dimm,l_err);
+ nvdimmAddUpdateRegs(iv_dimm,l_err);
}
}
}
@@ -1694,41 +1954,6 @@ errlHndl_t NvdimmInstalledImage::validateFwImage()
return l_err;
}
-errlHndl_t NvdimmInstalledImage::resetController()
-{
- errlHndl_t l_err = nullptr;
-
- // If bit 0 is set, the module shall start a Reset Controller operation
- l_err = nvdimmWriteReg(iv_dimm, NVDIMM_MGT_CMD0, 0x01);
- if (l_err)
- {
- TRACFCOMP(g_trac_nvdimm_upd,ERR_MRK"resetController: NVDIMM 0x%.8X "
- "write of 0x01 to NVDIMM_MGT_CMD0 register failed",
- TARGETING::get_huid(iv_dimm));
- }
- else
- {
- TRACUCOMP(g_trac_nvdimm_upd,"resetController: waiting 5 seconds after controller 0x%.8X reset",
- TARGETING::get_huid(iv_dimm));
-
- // sleep 5 seconds to allow for i2c controller to come back online
- nanosleep(5,0);
-
- TRACUCOMP(g_trac_nvdimm_upd,"resetController: now check if NV controller is ready again",
- TARGETING::get_huid(iv_dimm));
-
- // Now wait until NV controller is ready again after reset
- l_err = nvdimmReady(iv_dimm);
- if (l_err)
- {
- TRACFCOMP(g_trac_nvdimm_upd,ERR_MRK"resetController: NV controller for "
- "NVDIMM 0x%.8X is not reporting as ready after reset",
- TARGETING::get_huid(iv_dimm));
- }
- }
- return l_err;
-}
-
uint16_t NvdimmInstalledImage::crc16(const uint8_t * i_data, int i_data_size)
{
// From JEDEC JESD245B.01 document
@@ -1769,6 +1994,9 @@ bool NvdimmsUpdate::runUpdateUsingLid(NvdimmLidImage * i_lidImage,
errlHndl_t l_err = nullptr;
for (auto pInstalledImage : i_list)
{
+ TARGETING::Target * l_nvdimm = pInstalledImage->getNvdimmTarget();
+ uint64_t l_nvdimm_huid = TARGETING::get_huid(l_nvdimm);
+
INITSERVICE::sendProgressCode();
bool updateNeeded = false;
l_err = isUpdateNeeded(updateNeeded, i_lidImage, pInstalledImage);
@@ -1785,14 +2013,69 @@ bool NvdimmsUpdate::runUpdateUsingLid(NvdimmLidImage * i_lidImage,
}
else if (updateNeeded)
{
+ // shared trace variables
+ uint32_t l_installed_type = INVALID_TYPE;
+ l_err = pInstalledImage->getType(l_installed_type);
+ if (l_err)
+ {
+ // Continue updating other dimms
+ TRACFCOMP(g_trac_nvdimm_upd,
+ ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - "
+ "Unable to get nvdimm[0x%.8X] installed image type. "
+ "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid,
+ ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err));
+ commitPredictiveNvdimmError(l_err);
+ l_err = nullptr;
+ continue;
+ }
+
+ uint16_t l_oldVersion = INVALID_VERSION;
+ l_err = pInstalledImage->getVersion(l_oldVersion);
+ if (l_err)
+ {
+ // This shouldn't happen as getVersion should return a
+ // cached version
+ TRACFCOMP(g_trac_nvdimm_upd,
+ ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - "
+ "Failed to find current NVDIMM level of %.8X. "
+ "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid,
+ ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err));
+ commitPredictiveNvdimmError(l_err);
+ l_err = nullptr;
+ o_no_error_found = false;
+ continue;
+ }
+
// perform update for this DIMM with the current LID image
TRACFCOMP(g_trac_nvdimm_upd, "NvdimmsUpdate::runUpdateUsingLid() - "
- "now update nvdimm[0x%.8X]",
- TARGETING::get_huid(pInstalledImage->getNvdimmTarget()));
+ "now update nvdimm[0x%.8X]", l_nvdimm_huid);
TRACFCOMP(g_trac_nvdimm_upd,"Updating with flash size: 0x%08X",
i_lidImage->getFlashImageSize());
+ /*@
+ *@errortype INFORMATIONAL
+ *@reasoncode NVDIMM_START_UPDATE
+ *@moduleid NVDIMM_RUN_UPDATE_USING_LID
+ *@userdata1 NVDIMM Target Huid
+ *@userdata2[0:15] Old level (current)
+ *@userdata2[16:31] Update image level (new)
+ *@userdata2[32:63] Installed type (manufacturer and product)
+ *@devdesc Start of the NVDIMM update of this controller
+ *@custdesc NVDIMM update started
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ NVDIMM_RUN_UPDATE_USING_LID,
+ NVDIMM_START_UPDATE,
+ l_nvdimm_huid,
+ TWO_UINT16_ONE_UINT32_TO_UINT64(
+ l_oldVersion, i_lidImage->getVersion(),
+ l_installed_type),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ l_err->collectTrace(NVDIMM_UPD, 256);
+ ERRORLOG::errlCommit(l_err, NVDIMM_COMP_ID);
+ l_err = nullptr;
+
l_err = pInstalledImage->updateImage(i_lidImage);
if (l_err)
{
@@ -1803,14 +2086,150 @@ bool NvdimmsUpdate::runUpdateUsingLid(NvdimmLidImage * i_lidImage,
TRACFCOMP(g_trac_nvdimm_upd,
ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - "
"NVDIMM 0x%.8X NV controller update failed. "
- "RC=0x%X, PLID=0x%.8X",
- TARGETING::get_huid(pInstalledImage->getNvdimmTarget()),
+ "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid,
ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err));
commitPredictiveNvdimmError(l_err);
l_err = nullptr;
o_no_error_found = false;
+ continue;
+ }
+ else
+ {
+ // successfully updated this NVDIMM
+
+ // Note: call for version should just return a saved value
+ uint16_t curVersion = INVALID_VERSION;
+ l_err = pInstalledImage->getVersion(curVersion);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm_upd,
+ ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - "
+ "Failed to find current NVDIMM level of %.8X after "
+ "successful update. RC=0x%X, PLID=0x%.8X",
+ l_nvdimm_huid,
+ ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err));
+ commitPredictiveNvdimmError(l_err);
+ l_err = nullptr;
+ }
+
+ /*@
+ *@errortype INFORMATIONAL
+ *@reasoncode NVDIMM_UPDATE_COMPLETE
+ *@moduleid NVDIMM_RUN_UPDATE_USING_LID
+ *@userdata1[0:31] NVDIMM Target Huid
+ *@userdata1[32:63] Total region write retries
+ *@userdata2[0:15] Previous level
+ *@userdata2[16:31] Current updated level
+ *@userdata2[32:63] Installed type (manufacturer and product)
+ *@devdesc Successful update of NVDIMM code
+ *@custdesc NVDIMM was successfully updated
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ NVDIMM_RUN_UPDATE_USING_LID,
+ NVDIMM_UPDATE_COMPLETE,
+ TWO_UINT32_TO_UINT64(
+ l_nvdimm_huid,
+ pInstalledImage->getRegionWriteRetries()),
+ TWO_UINT16_ONE_UINT32_TO_UINT64(
+ l_oldVersion, curVersion,
+ l_installed_type),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT );
+ l_err->collectTrace(NVDIMM_UPD, 512);
+ ERRORLOG::errlCommit(l_err, NVDIMM_COMP_ID);
}
} // end of updateNeeded
+
+ /////////////////////////////////////////////////////////////////
+ // Should not exit the nvdimm update stage until each nvdimm
+ // is running at the lid's code level
+ // (or a predictive error was logged for that nvdimm)
+ /////////////////////////////////////////////////////////////////
+
+ // Check NVDIMM is at the latest level and it is running from slot 1
+ uint16_t l_curVersion = INVALID_VERSION;
+ l_err = pInstalledImage->getVersion(l_curVersion, true);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm_upd,
+ ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - "
+ "Failed to find current level of NVDIMM %.8X. "
+ "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid,
+ ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err));
+ commitPredictiveNvdimmError(l_err);
+ l_err = nullptr;
+ o_no_error_found = false;
+ continue;
+ }
+ uint8_t l_slot_running = 0;
+ l_err = nvdimmGetRunningSlot(l_nvdimm, l_slot_running);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm_upd,
+ ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - "
+ "Failed to find running slot of NVDIMM %.8X. "
+ "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid,
+ ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err));
+ commitPredictiveNvdimmError(l_err);
+ l_err = nullptr;
+ o_no_error_found = false;
+ continue;
+ }
+
+ if ((l_slot_running == 0) || (l_curVersion != i_lidImage->getVersion()))
+ {
+ // Not running latest code on this NVDIMM
+ TRACFCOMP(g_trac_nvdimm_upd,
+ ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - "
+ "NVDIMM %.8X running from slot %d with code level "
+ "0x%04X (lid level: 0x%04X)",
+ l_nvdimm_huid, l_slot_running, l_curVersion,
+ i_lidImage->getVersion());
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_NOT_RUNNING_LATEST_LEVEL
+ *@severity ERRORLOG_SEV_PREDICTIVE
+ *@moduleid NVDIMM_RUN_UPDATE_USING_LID
+ *@userdata1 NVDIMM Target Huid
+ *@userdata2[0:15] NVDIMM slot
+ *@userdata2[16:31] slot1 version
+ *@userdata2[32:47] latest version from lid
+ *@devdesc Encountered error after update while checking
+ * if NVDIMM is running latest code level
+ *@custdesc NVDIMM not running latest firmware level
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NVDIMM_RUN_UPDATE_USING_LID,
+ NVDIMM_NOT_RUNNING_LATEST_LEVEL,
+ l_nvdimm_huid,
+ FOUR_UINT16_TO_UINT64(
+ l_slot_running,
+ l_curVersion,
+ i_lidImage->getVersion(),
+ 0x0000),
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace( NVDIMM_COMP_NAME );
+
+ // Add callout of nvdimm with no deconfig/gard
+ l_err->addHwCallout( l_nvdimm,
+ HWAS::SRCI_PRIORITY_LOW,
+ HWAS::NO_DECONFIG,
+ HWAS::GARD_NULL);
+
+ // Maybe vendor log will tell why it isn't running latest code level
+ nvdimmAddVendorLog(l_nvdimm, l_err);
+ commitPredictiveNvdimmError(l_err);
+ l_err = nullptr;
+ o_no_error_found = false;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_nvdimm_upd,
+ "NvdimmsUpdate::runUpdateUsingLid() - "
+ "NVDIMM %.8X running from slot %d with latest level 0x%04X",
+ l_nvdimm_huid, l_slot_running, l_curVersion);
+ }
}
return o_no_error_found;
}
@@ -1826,12 +2245,15 @@ bool NvdimmsUpdate::runUpdate(void)
// List of each installed NVDIMM type
std::vector<NvdimmInstalledImage*> v_NVDIMM_16GB_list;
std::vector<NvdimmInstalledImage*> v_NVDIMM_32GB_list;
+ BPM::bpmList_t NVDIMM_BPM_16GB_list;
+ BPM::bpmList_t NVDIMM_BPM_32GB_list;
// Build up installed NVDIMM image lists
for (auto l_nvdimm : iv_nvdimmList)
{
NvdimmInstalledImage * l_installed_image =
new NvdimmInstalledImage(l_nvdimm);
+
l_err = l_installed_image->getType(l_installed_type);
if (l_err)
{
@@ -1843,6 +2265,10 @@ bool NvdimmsUpdate::runUpdate(void)
ERRL_GETPLID_SAFE(l_err));
commitPredictiveNvdimmError(l_err);
o_no_error_found = false;
+
+ // Delete the unused NvdimmInstalledImage pointer
+ delete l_installed_image;
+
continue;
}
@@ -1852,6 +2278,10 @@ bool NvdimmsUpdate::runUpdate(void)
"0x%.8X NVDIMM is SMART_NVDIMM_16GB_TYPE",
get_huid(l_nvdimm));
v_NVDIMM_16GB_list.push_back(l_installed_image);
+
+ BPM::Bpm l_16gbBpm(l_nvdimm);
+ NVDIMM_BPM_16GB_list.push_back(l_16gbBpm);
+
}
else if (l_installed_type == SMART_NVDIMM_32GB_TYPE)
{
@@ -1859,6 +2289,9 @@ bool NvdimmsUpdate::runUpdate(void)
"0x%.8X NVDIMM is SMART_NVDIMM_32GB_TYPE",
get_huid(l_nvdimm));
v_NVDIMM_32GB_list.push_back(l_installed_image);
+
+ BPM::Bpm l_32gbBpm(l_nvdimm);
+ NVDIMM_BPM_32GB_list.push_back(l_32gbBpm);
}
else
{
@@ -1866,7 +2299,7 @@ bool NvdimmsUpdate::runUpdate(void)
TRACFCOMP(g_trac_nvdimm_upd, "NvdimmsUpdate::runUpdate() - unknown "
"nvdimm[%X] installed type 0x%04X, skipping update",
TARGETING::get_huid(l_nvdimm), l_installed_type);
- /*
+ /*@
*@errortype
*@reasoncode NVDIMM_UNSUPPORTED_NVDIMM_TYPE
*@moduleid NVDIMM_RUN_UPDATE
@@ -1889,36 +2322,34 @@ bool NvdimmsUpdate::runUpdate(void)
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
l_err->collectTrace(NVDIMM_UPD, 256);
+ nvdimmAddVendorLog(l_nvdimm, l_err);
l_err->addPartCallout( l_nvdimm,
HWAS::NV_CONTROLLER_PART_TYPE,
HWAS::SRCI_PRIORITY_HIGH );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
+ nvdimmAddPage4Regs(l_nvdimm,l_err);
+ nvdimmAddUpdateRegs(l_nvdimm,l_err);
ERRORLOG::errlCommit(l_err, NVDIMM_COMP_ID);
+
+ // Delete the unused NvdimmInstalledImage object
+ delete l_installed_image;
+
continue;
}
}
do {
- // First check that updatable NVDIMMs exist on the system
- if ((v_NVDIMM_16GB_list.size() == 0) &&
- (v_NVDIMM_32GB_list.size() == 0))
- {
- TRACFCOMP(g_trac_nvdimm_upd, "NvdimmsUpdate::runUpdate() - "
- "No updatable NVDIMMs present on the system");
- break;
- }
-
- /////////////////////////
- // @todo: remove this check when SMART provides updated 32GB image
- // The current 32GB image will cause the future updating to fail
- if (v_NVDIMM_16GB_list.size() == 0)
+ // First check that updatable NVDIMMs or BPMs exist on the system
+ if ( (v_NVDIMM_16GB_list.size() == 0)
+ && (v_NVDIMM_32GB_list.size() == 0)
+ && (NVDIMM_BPM_16GB_list.size() == 0)
+ && (NVDIMM_BPM_32GB_list.size() == 0))
{
TRACFCOMP(g_trac_nvdimm_upd, "NvdimmsUpdate::runUpdate() - "
- "Only 16GB NVDIMM type is supported right now for update");
+ "No updatable NVDIMMs or BPMs present on the system");
break;
}
- /////////////////////////
if (INITSERVICE::spBaseServicesEnabled())
{
@@ -1935,7 +2366,15 @@ bool NvdimmsUpdate::runUpdate(void)
break;
}
- for(const auto& lid : info.lidIds)
+ // Both the config and firmware images are needed to perform an
+ // update on a BPM. So, get pointers to each in the CompInfo
+ // struct's vector of LID IDs.
+ MCL::LidInfo * bpm_16gb_fw = nullptr;
+ MCL::LidInfo * bpm_16gb_config = nullptr;
+ MCL::LidInfo * bpm_32gb_fw = nullptr;
+ MCL::LidInfo * bpm_32gb_config = nullptr;
+
+ for(auto& lid : info.lidIds)
{
TRACFCOMP(g_trac_nvdimm,"LID ID=0x%08X, size=%d, vAddr=%p",
lid.id, lid.size, lid.vAddr);
@@ -1966,6 +2405,22 @@ bool NvdimmsUpdate::runUpdate(void)
v_NVDIMM_32GB_list);
}
}
+ else if (lid.id == NVDIMM_32GB_BPM_FW_LIDID)
+ {
+ bpm_32gb_fw = &lid;
+ }
+ else if (lid.id == NVDIMM_32GB_BPM_CONFIG_LIDID)
+ {
+ bpm_32gb_config = &lid;
+ }
+ else if (lid.id == NVDIMM_16GB_BPM_FW_LIDID)
+ {
+ bpm_16gb_fw = &lid;
+ }
+ else if (lid.id == NVDIMM_16GB_BPM_CONFIG_LIDID)
+ {
+ bpm_16gb_config = &lid;
+ }
else if (lid.id != NVDIMM_SIGNATURE_LIDID)
{
TRACFCOMP(g_trac_nvdimm, "NvdimmsUpdate::runUpdate() - "
@@ -1975,6 +2430,26 @@ bool NvdimmsUpdate::runUpdate(void)
}
}
+ // Run BPM updates on NVDIMMs
+ BPM::BpmFirmwareLidImage fwImage_16gb(bpm_16gb_fw->vAddr,
+ bpm_16gb_fw->size);
+
+ BPM::BpmFirmwareLidImage fwImage_32gb(bpm_32gb_fw->vAddr,
+ bpm_32gb_fw->size);
+
+ BPM::BpmConfigLidImage configImage_16gb(bpm_16gb_config->vAddr,
+ bpm_16gb_config->size);
+
+ BPM::BpmConfigLidImage configImage_32gb(bpm_32gb_config->vAddr,
+ bpm_32gb_config->size);
+
+ BPM::runBpmUpdates(&NVDIMM_BPM_16GB_list,
+ &NVDIMM_BPM_32GB_list,
+ &fwImage_16gb,
+ &fwImage_32gb,
+ &configImage_16gb,
+ &configImage_32gb);
+
// Destructor automatically unloads the NVDIMM flash binary
}
else
@@ -1987,6 +2462,16 @@ bool NvdimmsUpdate::runUpdate(void)
}
} while (0); // end of flash update section
+ // Clean up the pointers used in v_NVDIMM_16GB_list and v_NVDIMM_32GB_list
+ for (const auto& pInstalledImage : v_NVDIMM_16GB_list)
+ {
+ delete pInstalledImage;
+ }
+ for (const auto& pInstalledImage : v_NVDIMM_32GB_list)
+ {
+ delete pInstalledImage;
+ }
+
return o_no_error_found;
}
@@ -2001,7 +2486,7 @@ errlHndl_t NvdimmsUpdate::isUpdateNeeded(bool & o_update_needed,
uint32_t curType = INVALID_TYPE;
do {
- const TARGETING::Target * l_dimm = i_cur_image->getNvdimmTarget();
+ TARGETING::Target * l_dimm = i_cur_image->getNvdimmTarget();
// check Types match (same manufacturer and product)
lidType = i_lid_image->getType();
@@ -2038,7 +2523,7 @@ errlHndl_t NvdimmsUpdate::isUpdateNeeded(bool & o_update_needed,
"isUpdateNeeded(): non-updatable SMART NVDIMM 0x%.8X "
"(0x%04X)",
TARGETING::get_huid(l_dimm), le16toh(curVersion));
- /*
+ /*@
*@errortype
*@reasoncode NVDIMM_UPDATE_NOT_SUPPORTED
*@moduleid NVDIMM_IS_UPDATE_NEEDED
@@ -2046,9 +2531,9 @@ errlHndl_t NvdimmsUpdate::isUpdateNeeded(bool & o_update_needed,
*@userdata1[32:63] NVDIMM Target Huid
*@userdata2 NVDIMM type (manufacturer and product)
*@devdesc Unable to update an NVDIMM at this code level
- *@custdesc NVDIMM not updated
+ *@custdesc Unsupported level of NVDIMM hardware
*/
- l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
NVDIMM_IS_UPDATE_NEEDED,
NVDIMM_UPDATE_NOT_SUPPORTED,
TWO_UINT32_TO_UINT64(
@@ -2057,9 +2542,15 @@ errlHndl_t NvdimmsUpdate::isUpdateNeeded(bool & o_update_needed,
curType,
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
l_err->collectTrace( NVDIMM_UPD, 256 );
+ nvdimmAddVendorLog(const_cast<TARGETING::Target*>(l_dimm),
+ l_err);
+ l_err->addHwCallout( l_dimm,
+ HWAS::SRCI_PRIORITY_HIGH,
+ HWAS::DECONFIG,
+ HWAS::GARD_Fatal);
l_err->addPartCallout( l_dimm,
HWAS::NV_CONTROLLER_PART_TYPE,
- HWAS::SRCI_PRIORITY_HIGH );
+ HWAS::SRCI_PRIORITY_MED );
l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE,
HWAS::SRCI_PRIORITY_LOW );
break;
OpenPOWER on IntegriCloud