diff options
author | Matt Derksen <mderkse1@us.ibm.com> | 2019-06-27 15:03:42 -0500 |
---|---|---|
committer | Daniel M Crowell <dcrowell@us.ibm.com> | 2020-01-20 10:23:06 -0600 |
commit | 829e56fb1456d699806f8e69ebddf7835c1ae633 (patch) | |
tree | 1b92407305312ea3983f817c45866e8d98755ec6 /src/usr/i2c | |
parent | 1cb00f7e0e9c6cd2646d7e0245a5f22ecf97ab0c (diff) | |
download | talos-hostboot-829e56fb1456d699806f8e69ebddf7835c1ae633.tar.gz talos-hostboot-829e56fb1456d699806f8e69ebddf7835c1ae633.zip |
NVDIMM: Use block write for nvdimm update
In an effort to speed up the nvdimm update, full 32-byte
blocks can now be sent via I2C SMBUS with no initial byte count byte.
Since a block write seems more prone to random system interrupt, this
code should be restricted to run on v3.A or beyond which has the
timeout increased to mitigate these interrupts.
Test results have shown about a 5 minute improvement per NVDIMM.
Change-Id: I040a5f2cc5afb76a73129ef9f6ac965cf36775f4
CQ: SW471053
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/79678
Reviewed-by: Corey V Swenson <cswenson@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: TSUNG K YEUNG <tyeung@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: Daniel M Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/i2c')
-rwxr-xr-x | src/usr/i2c/i2c.C | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C index 226b96acf..2439f1eff 100755 --- a/src/usr/i2c/i2c.C +++ b/src/usr/i2c/i2c.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2019 */ +/* Contributors Listed Below - COPYRIGHT 2011,2020 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -448,10 +448,11 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, // Else this is not a page operation, call the normal common function else { - if( (subop==DeviceFW::I2C_SMBUS_BLOCK) - || (subop==DeviceFW::I2C_SMBUS_BYTE) - || (subop==DeviceFW::I2C_SMBUS_WORD) - || (subop == DeviceFW::I2C_SMBUS_WORD_NO_PEC) ) + if( (subop == DeviceFW::I2C_SMBUS_BLOCK) + || (subop == DeviceFW::I2C_SMBUS_BYTE) + || (subop == DeviceFW::I2C_SMBUS_WORD) + || (subop == DeviceFW::I2C_SMBUS_WORD_NO_PEC) + || (subop == DeviceFW::I2C_SMBUS_BLOCK_NO_BYTE_COUNT) ) { args.smbus.commandCode = static_cast<decltype(args.smbus.commandCode)>( @@ -487,6 +488,11 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, args.smbus.usePec = false; args.subop = DeviceFW::I2C_SMBUS_WORD; } + else if (subop == DeviceFW::I2C_SMBUS_BLOCK_NO_BYTE_COUNT) + { + args.smbus.usePec = false; + args.subop=subop; + } else { args.subop=subop; @@ -1450,7 +1456,8 @@ errlHndl_t i2cCommonOp( DeviceFW::OperationType i_opType, /*******************************************************/ /* Perform the I2C Operation */ /*******************************************************/ - + TRACUCOMP( g_trac_i2c, INFO_MRK "i2cCommonOp() -- opType: %d, subOp: %d", + static_cast<uint64_t>(i_opType), i_args.subop); /***********************************************/ /* I2C SMBUS Send Byte */ /***********************************************/ @@ -1618,14 +1625,16 @@ errlHndl_t i2cCommonOp( DeviceFW::OperationType i_opType, /***********************************************/ /* I2C SMBUS Block Write */ /***********************************************/ - else if( (i_opType == DeviceFW::WRITE ) - && (i_args.subop == DeviceFW::I2C_SMBUS_BLOCK)) + else if( (i_opType == DeviceFW::WRITE ) && + ((i_args.subop == DeviceFW::I2C_SMBUS_BLOCK) || + (i_args.subop == DeviceFW::I2C_SMBUS_BLOCK_NO_BYTE_COUNT)) ) { TRACUCOMP(g_trac_i2c, INFO_MRK - "I2C SMBUS Block Write: Command code = 0x%02X, " - "Use PEC = %d. io_buflen = %lu", - i_args.smbus.commandCode, - i_args.smbus.usePec, io_buflen); + "I2C SMBUS Block Write: Command code = 0x%02X, SubCmd = 0x%02X " + "Use PEC = %d. io_buflen = %lu, io_buffer byte0: 0x%02X", + i_args.smbus.commandCode, i_args.subop, + i_args.smbus.usePec, io_buflen, + *reinterpret_cast<uint8_t*>(io_buffer)); // If requested length is for < 1 byte or > 255 bytes for a block // write transaction, throw an error. @@ -1669,12 +1678,29 @@ errlHndl_t i2cCommonOp( DeviceFW::OperationType i_opType, io_buflen, io_buffer, i_args.smbus.usePec); + void * writeStart = &blockWrite.commandCode; + + // byteCount might be altered into commandCode, so store its value + size_t dataByteCount = blockWrite.byteCount; + if (i_args.subop == DeviceFW::I2C_SMBUS_BLOCK_NO_BYTE_COUNT) + { + // Moving commandCode down a byte so it is followed + // immediately by dataBytes[] instead of byteCount + // (this removes byteCount from the block write) + writeStart = &blockWrite.byteCount; + blockWrite.byteCount = blockWrite.commandCode; + blockWrite.messageSize -= sizeof(blockWrite.commandCode); + TRACUCOMP(g_trac_i2c, INFO_MRK + "I2C SMBUS Block Write no-byte-count: removing byteCount," + " msgSize = %d", blockWrite.messageSize); + } + do { size_t writeSize = blockWrite.messageSize; const auto writeSizeExp = writeSize; err = i2cWrite(i_target, - &blockWrite.commandCode, + writeStart, writeSize, i_args); if(err) @@ -1686,7 +1712,8 @@ errlHndl_t i2cCommonOp( DeviceFW::OperationType i_opType, "Write size mismatch; expected %d but got %d", writeSizeExp,writeSize); - io_buflen = blockWrite.byteCount; + + io_buflen = dataByteCount; } while(0); |