From 0cc0c9689387691a9b2bec37386d79c6d4eb8e87 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 27 Apr 2026 10:01:06 +0800 Subject: [PATCH] dimm-spd-reader: fix PMIC type detection from SPD Add support for identifying PMIC unknown state as 0xFF. Update PMIC SPD detection flow to read SPD registers 0x200, 0x204, and 0x208. Check bit7 to determine whether the PMIC is installed, and use SPD bit[3:0] as the PMIC type. Also update the IPMI error handling path to return completion code 0x07 for command 0x6c when PMIC detection fails or the PMIC type is unknown. --- 0001-LUXSHARE_2026041701.patch | 425 ++++++++++++++++++ .../dimm/dimm-spd-reader/dimmSpdReader.cpp | 273 ++++++++--- .../dimm/dimm-spd-reader/dimmSpdReader.hpp | 12 +- .../dimm-spd-reader/dimmSpdReaderMain.cpp | 9 + .../ipmi-lux-oem/ipmi-oem/ipmi-oem.cpp | 36 +- .../ipmi-lux-oem/ipmi-oem/ipmi-oem.hpp | 10 +- 6 files changed, 697 insertions(+), 68 deletions(-) create mode 100644 0001-LUXSHARE_2026041701.patch diff --git a/0001-LUXSHARE_2026041701.patch b/0001-LUXSHARE_2026041701.patch new file mode 100644 index 00000000..409a8940 --- /dev/null +++ b/0001-LUXSHARE_2026041701.patch @@ -0,0 +1,425 @@ +From 182a0516acfeffabf6f2ec863d078d3ef72b0265 Mon Sep 17 00:00:00 2001 +From: Your Name +Date: Thu, 23 Apr 2026 17:48:19 +0800 +Subject: [PATCH] LUXSHARE_2026041701 + +--- + .../dimm/dimm-spd-reader/dimmSpdReader.cpp | 281 ++++++++++++++---- + 1 file changed, 229 insertions(+), 52 deletions(-) + +diff --git a/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.cpp b/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.cpp +index cd730713..7438cbd3 100755 +--- a/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.cpp ++++ b/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.cpp +@@ -346,7 +346,7 @@ static int i3cWriteRead(std::string& i3cDev, uint8_t wBuf[], uint16_t wLen, + std::cout << "i3c data to write:" << std::endl; + for(int i=0; isecond.error)); + } else { + std::cout << "Invalid size for error array!" << std::endl; + } break; - default: std::cout << "Unknown field type!" << std::endl; break; @@ -456,10 +462,10 @@ int DIMMSpdReader::getPmicType(uint8_t cpuid, uint8_t rank) uint8_t index[] = {0xc8, 0xcc, 0xd0}; uint16_t wLen = 2; -//Jim debug uint8_t wrBuf[] = {0, 0}; - uint8_t wrBuf[] = {0, 0, 0}; //Jim debug + uint8_t wrBuf[] = {0, 0, 0}; uint8_t rdBuf[] = {0}; uint16_t rLen = 1; + uint8_t typeVal = 0; int spd = NUM_TO_SPD(rank); const uint8_t memReg = 0x80; @@ -484,12 +490,16 @@ int DIMMSpdReader::getPmicType(uint8_t cpuid, uint8_t rank) { return -1; } - - if((rdBuf[0] & 0xf) == 0x6) - { - pmicType[cpuid][rank] = PMIC5030; - break; - } + + //SPD 0xc8, 0xcc, 0xd0 is Device Types + //Check DeviceType[7] = 1 is Installed + if((rdBuf[0] & 0x80) != 0) + { + //read DeviceType Bits[3:0] + typeVal = rdBuf[0] & 0xf; + pmicType[cpuid][rank] = (typeVal <= PMIC5030) ? static_cast(typeVal) : Unknown; + break; + } } if(pmicType[cpuid][rank] == PMIC5030) @@ -499,8 +509,6 @@ int DIMMSpdReader::getPmicType(uint8_t cpuid, uint8_t rank) gotType[cpuid][rank] = true; -//Jim debug+S - //---------------------------------------------------------------------------- //A. 1B Write R30 = 0x84 // 1 byte format, set 2 byte mode //B. 2B Read R0030 //check 2 byte mode @@ -516,7 +524,7 @@ int DIMMSpdReader::getPmicType(uint8_t cpuid, uint8_t rank) int pmic = NUM_TO_PMIC(rank); std::string i3cPmicName = I3C_ADDR(cpuid) + to_hex(pmic); - + if constexpr (debug) { std::cout << "is PMIC5030"<< std::endl; @@ -561,8 +569,8 @@ int DIMMSpdReader::getPmicType(uint8_t cpuid, uint8_t rank) if constexpr (debug) { std::cout << "Is 2 Byte mode" << std::endl; - } - } + } + } // It was originally 2 bytes mode else { @@ -571,7 +579,7 @@ int DIMMSpdReader::getPmicType(uint8_t cpuid, uint8_t rank) wLen = 3; rLen = 0; ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen); - + std::this_thread::sleep_for(std::chrono::milliseconds(9)); //C2-2. 2B Read R30 = 0x84 wrBuf[0] = 0x30; wrBuf[1] = 0x00; @@ -592,8 +600,9 @@ int DIMMSpdReader::getPmicType(uint8_t cpuid, uint8_t rank) } } + + -//Jim debug+E if constexpr (debug) { std::cout << "pmicType[" << (int)cpuid << "][" << (int)rank << "] = "<< (int)pmicType[cpuid][rank] << std::endl; @@ -736,10 +745,10 @@ int DIMMSpdReader::getDIMMRegsVol(uint8_t cpuid, uint8_t rank, DimmData& dimmDat int index = (pmicType[cpuid][rank] == PMIC5030) ? 6 : 4; for(int i=0; i= MAX_CPU_ID || rank >= MAX_DIMM_RANK) return ret; + + if constexpr (debug) + { + std::cout << "Start to check ADC Accuracy Step Size."<< std::endl; + } + + uint16_t wLen; + uint16_t rLen; + uint8_t rdBuf[] = {0}; + uint8_t wrBuf[3] = {0, 0, 0}; + uint16_t ThresholdSel[6] = {0x1C, 0x1D, 0x1E, 0x1F, 0x11A, 0x11B}; //OUTPUT_HIGH_CURRENT_CONSUMPTION_WARNING_THRESHOLD + + int pmic = NUM_TO_PMIC(rank); + std::string i3cPmicName = I3C_ADDR(cpuid) + to_hex(pmic); + + // 1. Read R32 + rLen = 1; + wLen = 2; + wrBuf[0] = 0x32; //address_Low + wrBuf[1] = 0; //address_High + ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen); + if (ret < 0) + { + return -1; + } + if((rdBuf[0] & 0x3) != 1) + { + dimmData.error[0] |= 1; + } + + // 2. Read ThresholdSel {0x1C, 0x1D, 0x1E, 0x1F, 0x11A, 0x11B} + rLen = 1; + wLen = 2; + for(int i=0; i<6; i++) { + wrBuf[0] = static_cast(ThresholdSel[i] & 0xFF); //address_Low + wrBuf[1] = static_cast((ThresholdSel[i]>>8) & 0xFF); //address_High + ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen); + if (ret < 0) + { + return -1; + } + if(rdBuf[0] != TargetData[i]) + { + dimmData.error[0] |= 1<<(i+1); + } + } + return ret; +} + +int DIMMSpdReader::setADCAccuracyStepSize(uint8_t cpuid, uint8_t rank, DimmData& dimmData, uint8_t R32) +{ + int ret = -1; + if(cpuid >= MAX_CPU_ID || rank >= MAX_DIMM_RANK) return ret; + + + if constexpr (debug) + { + std::cout << "Start to set Pmic5030 ADC Accuracy Step Size."<< std::endl; + } + + uint16_t wLen; + uint16_t rLen; + uint8_t rdBuf[] = {0}; + uint8_t wrBuf[3] = {0, 0, 0}; + uint16_t ThresholdSel[6] = {0x1C, 0x1D, 0x1E, 0x1F, 0x11A, 0x11B}; //OUTPUT_HIGH_CURRENT_CONSUMPTION_WARNING_THRESHOLD + uint8_t ThresholdData[6] = {0, 0, 0, 0, 0, 0}; + uint8_t TargetData[6] = {0, 0, 0, 0, 0, 0}; + uint8_t adcAcc[] = {0x32, 0, 0}; + uint32_t calcData = 0; + constexpr int PMIC_CHANNEL_SWD_INDEX = 3; + constexpr uint8_t PMIC_MAX_CUR_7500MA_REG_VAL = 0xF0; // SWA, SWB, SWC, SWE, SWF + constexpr uint8_t PMIC_MAX_CUR_5000MA_REG_VAL = 0xA0; // SWD + + int pmic = NUM_TO_PMIC(rank); + std::string i3cPmicName = I3C_ADDR(cpuid) + to_hex(pmic); + + // 1. Read ThresholdSel {0x1C, 0x1D, 0x1E, 0x1F, 0x11A, 0x11B} + rLen = 1; + wLen = 2; + for(int i=0; i<6; i++) { + wrBuf[0] = static_cast(ThresholdSel[i] & 0xFF); //address_Low + wrBuf[1] = static_cast((ThresholdSel[i]>>8) & 0xFF); //address_High + ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, &ThresholdData[i], rLen); + if (ret < 0) + { + return -1; + } + } + + // 2. Write R32[1:0] = 01b + adcAcc[2] = (R32&0xFC)|0x1; + wLen = 3; + rLen = 0; + ret = i3cWriteRead(i3cPmicName, adcAcc, wLen, rdBuf, rLen); + if (ret < 0) + { + //std::cerr << " read word data failed. \n"; + return -1; + } + + // 3. Write ThresholdData + for(int i=0; i<6; i++) { + rLen = 0; + wLen = 3; + wrBuf[0] = static_cast(ThresholdSel[i] & 0xFF); //address_Low + wrBuf[1] = static_cast((ThresholdSel[i]>>8) & 0xFF); //address_High + + //data + calcData = (ThresholdData[i] * 4); // 125/31.25 = 4 + + if (i == PMIC_CHANNEL_SWD_INDEX) { + // SWD Maximum current is 5000mA + TargetData[i] = (calcData > PMIC_MAX_CUR_5000MA_REG_VAL) ? PMIC_MAX_CUR_5000MA_REG_VAL : static_cast(calcData); + } + else { + // SWA, SWB, SWC, SWE, SWF Maximum current is 7500mA + TargetData[i] = (calcData > PMIC_MAX_CUR_7500MA_REG_VAL) ? PMIC_MAX_CUR_7500MA_REG_VAL : static_cast(calcData); + } + wrBuf[2] = TargetData[i]; + + ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen); + if (ret < 0) + { + return -1; + } + } + + ret = checkADCAccuracyStepSize(cpuid, rank, dimmData, TargetData); + if (ret < 0) + { + //std::cerr << " set ADCAccuracy Step Size failed. \n"; + return -1; + } + + return ret; +} + int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& dimmData) { @@ -828,8 +976,7 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d uint8_t adcSelect[] = {0x1b, 0, 0}; uint16_t curOut[8]; uint8_t temp[8]; - uint8_t rdBuf[] = {0, 0, 0, 0, 0, 0, 0, 0}; //Jim debug, For Renesas requirements, I3C command: Continuously read R100~R107 -//Jim debug uint8_t rdBuf[] = {0}; + uint8_t rdBuf[] = {0, 0, 0, 0, 0, 0, 0, 0}; //For Renesas requirements, I3C command: Continuously read R100~R107 uint8_t wrBuf[] = {0, 0}; int pmic = NUM_TO_PMIC(rank); @@ -846,6 +993,20 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d return -1; } if((rdBuf[0] & 0x3) == 1) accStep31 = true; + else + { + if(twoByteMode[cpuid][rank]) + { + //if two Byte Mode + PMIC5030, R32[1:0] set 01b + ret = setADCAccuracyStepSize(cpuid, rank, dimmData, rdBuf[0]); + accStep31 = true; + if (ret < 0) + { + //std::cerr << " set ADCAccuracy Step Size failed. \n"; + return -1; + } + } + } if constexpr (debug) { std::cout << "accStep31: " << (int)accStep31 << std::endl; @@ -886,7 +1047,7 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d adcSelect[1] = rdBuf[0] & 0xbf; //Read current wLen = 2; } - rLen = 0; //Jim debug, For Renesas requirements, I3C write commands cannot be directly read; reading requires a separate I3C command. + rLen = 0; //For Renesas requirements, I3C write commands cannot be directly read; reading requires a separate I3C command. ret = i3cWriteRead(i3cPmicName, adcSelect, wLen, rdBuf, rLen); if (ret < 0) { @@ -916,13 +1077,6 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d { return -1; } - else - { - for(int i=0; i<6; i++) - { - dimmData.current[i] = calStep31CurPower(i, temp); - } - } } ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen); @@ -963,10 +1117,10 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d } dimmData.current[i] = rdBuf[0] * 125.0 / 1000.0; - + } } - + //start to read power if(twoByteMode[cpuid][rank]) @@ -979,7 +1133,7 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d adcSelect[1] |= 0x40; wLen = 2; } - rLen = 0; //Jim debug, For Renesas requirements, I3C write commands cannot be directly read; reading requires a separate I3C command. + rLen = 0; //For Renesas requirements, I3C write commands cannot be directly read; reading requires a separate I3C command. ret = i3cWriteRead(i3cPmicName, adcSelect, wLen, rdBuf, rLen); if (ret < 0) { @@ -1009,13 +1163,6 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d { return -1; } - else - { - for(int i=0; i<6; i++) - { - dimmData.current[i] = calStep31CurPower(i, temp); - } - } } ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen); @@ -1026,7 +1173,7 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d for(int i=0; i::quiet_NaN(), std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}, @@ -1113,7 +1261,7 @@ void DIMMSpdReader::init() dimmDataTable.insert_or_assign(dimmName, std::move(dData)); - pmicType[cpuid][i] = PMIC5010; + pmicType[cpuid][i] = Unknown; gotType[cpuid][i] = false; twoByteMode[cpuid][i] = false; } @@ -1131,21 +1279,19 @@ void DIMMSpdReader::readDimmInfo() for(int cpuid=0; cpuid::quiet_NaN(), std::numeric_limits::quiet_NaN(), - std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), - std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}, - {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), - std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), - std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}, - {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), - std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), - std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}, - {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), - std::numeric_limits::quiet_NaN()}}; - std::string dimmName = "DIMM_CPU" + std::string(1, '0' + cpuid) + "_" + std::string(1, 'A' + i); + DimmData dData = dimmDataTable[dimmName]; + for (int j = 0; j < STATUS_TEMP_NUM; j++) { + dData.temp[j] = std::numeric_limits::quiet_NaN(); + } + for (int j = 0; j < STATUS_PMIC_RAIL_NUM; j++) { + dData.voltage[j] = std::numeric_limits::quiet_NaN(); + dData.current[j] = std::numeric_limits::quiet_NaN(); + dData.power[j] = std::numeric_limits::quiet_NaN(); + } + for (int j = 0; j < STATUS_REG_NUM; j++) { + dData.reg[j] = 0; + } int index = cpuid * 4 + i / 3; if(index != lastIndex) { @@ -1211,6 +1357,7 @@ void DIMMSpdReader::readDimmInfo() updateField(dimmName, CURRENT, dData.current, STATUS_PMIC_RAIL_NUM); updateField(dimmName, POWER, dData.power, STATUS_PMIC_RAIL_NUM); + updateField(dimmName, ERROR, dData.error, STATUS_ERROR_NUM); } #endif } @@ -1266,6 +1413,11 @@ void DIMMSpdReader::updateDbus() dimm_statusReg_inf[data.first]->set_property("0x0a", data.second.reg[6]); dimm_statusReg_inf[data.first]->set_property("0x0b", data.second.reg[7]); } + + if(dimm_errCode_inf.find(data.first) != dimm_errCode_inf.end()) { + dimm_errCode_inf[data.first]->set_property("0x32", data.second.error[0]); + } + } } @@ -1320,6 +1472,9 @@ void DIMMSpdReader::updateToDimmInfoFile() js[data.first]["Status_Reg"]["0x09"] = data.second.reg[5]; js[data.first]["Status_Reg"]["0x0a"] = data.second.reg[6]; js[data.first]["Status_Reg"]["0x0b"] = data.second.reg[7]; + + //update error code + js[data.first]["Error_Code"]["0x32"] = data.second.error[0]; } jsonOutputFile << js.dump(4); @@ -1355,7 +1510,7 @@ void DIMMSpdReader::setupMatches(sdbusplus::bus_t& connection) if (ret != 0) { std::cout << "Failed to modprobe dw-i3c-master module" << std::endl; return; - } + } std::this_thread::sleep_for(std::chrono::milliseconds(500)); //switch dimm i3c to bmc std::cout << "start to Read" << std::endl; diff --git a/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.hpp b/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.hpp index b70ea48d..07c75753 100755 --- a/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.hpp +++ b/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.hpp @@ -16,28 +16,33 @@ #define STATUS_TEMP_NUM 3 #define STATUS_PMIC_RAIL_NUM 6 #define STATUS_REG_NUM 8 +#define STATUS_ERROR_NUM 1 extern std::unordered_map> dimm_temp_inf; extern std::unordered_map> dimm_voltage_inf; extern std::unordered_map> dimm_current_inf; extern std::unordered_map> dimm_power_inf; extern std::unordered_map> dimm_statusReg_inf; +extern std::unordered_map> dimm_errCode_inf; enum FieldType { VOLTAGE, CURRENT, POWER, TEMP, - STATUS + STATUS, + ERROR }; struct DimmData { uint8_t reg[STATUS_REG_NUM]; + uint8_t error[STATUS_ERROR_NUM]; double voltage[STATUS_PMIC_RAIL_NUM]; double current[STATUS_PMIC_RAIL_NUM]; double power[STATUS_PMIC_RAIL_NUM]; double temp[STATUS_TEMP_NUM]; + }; struct DimmI3CAddr @@ -53,7 +58,8 @@ enum PMICType { PMIC5020, PMIC5120, PMIC5200, - PMIC5030 + PMIC5030, + Unknown = 0xFF }; struct DIMMSpdReader : std::enable_shared_from_this @@ -81,6 +87,8 @@ struct DIMMSpdReader : std::enable_shared_from_this void getdimmI3cSwitchState(const std::shared_ptr& conn, size_t retries = 2); int getPmicType(uint8_t cpuid, uint8_t rank); int getPmicStatusRegs(uint8_t cpuid, uint8_t rank, DimmData& dimmData); + int setADCAccuracyStepSize(uint8_t cpuid, uint8_t rank, DimmData& dimmData, uint8_t R32); + int checkADCAccuracyStepSize(uint8_t cpuid, uint8_t rank, DimmData& dimmData, const uint8_t* ThresholdData); private: std::vector matches; diff --git a/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReaderMain.cpp b/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReaderMain.cpp index f4efaa44..d931216b 100755 --- a/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReaderMain.cpp +++ b/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReaderMain.cpp @@ -59,6 +59,8 @@ std::unordered_map std::unordered_map> dimm_current_inf; std::unordered_map> dimm_power_inf; std::unordered_map> dimm_statusReg_inf; +std::unordered_map> dimm_errCode_inf; + int main() { @@ -177,6 +179,13 @@ int main() dimm_statusReg_inf[dimm]->register_property( "0x0b", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite); dimm_statusReg_inf[dimm]->initialize(); + + dimm_errCode_inf[dimm] = objectServer.add_interface(interfacePath, + "xyz.openbmc_project.Dimm.ErrCode"); + dimm_errCode_inf[dimm]->register_property( + "0x32", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite); + dimm_errCode_inf[dimm]->initialize(); + } double pollRate = 0.1; diff --git a/meta-luxshare/meta-common/recipes-luxshare/ipmi-lux-oem/ipmi-oem/ipmi-oem.cpp b/meta-luxshare/meta-common/recipes-luxshare/ipmi-lux-oem/ipmi-oem/ipmi-oem.cpp index e0408f6d..6989e3dd 100755 --- a/meta-luxshare/meta-common/recipes-luxshare/ipmi-lux-oem/ipmi-oem/ipmi-oem.cpp +++ b/meta-luxshare/meta-common/recipes-luxshare/ipmi-lux-oem/ipmi-oem/ipmi-oem.cpp @@ -1374,7 +1374,7 @@ ipmi::RspType ipmiBiosSetDimmPara(ipmi::Context::ptr ctx, std::vector(dimmInfo.dimmCur.SWD) / 1000.0; railData[4] = static_cast(dimmInfo.dimmCur.SWE) / 1000.0; railData[5] = static_cast(dimmInfo.dimmCur.SWF) / 1000.0; - for(int i=0; i<4; i++) { + for(int i=0; i<6; i++) { //Jim debug check i<6 or i<4 ret = setDimmParaToDbus(ctx, dimmName, "Current", railName[i], railData[i]); if(ret < 0) return ipmi::responseUnspecifiedError(); @@ -1387,7 +1387,7 @@ ipmi::RspType ipmiBiosSetDimmPara(ipmi::Context::ptr ctx, std::vector(dimmInfo.dimmPow.SWD) / 1000.0; railData[4] = static_cast(dimmInfo.dimmPow.SWE) / 1000.0; railData[5] = static_cast(dimmInfo.dimmPow.SWF) / 1000.0; - for(int i=0; i<4; i++) { + for(int i=0; i<6; i++) { //Jim debug check i<6 or i<4 ret = setDimmParaToDbus(ctx, dimmName, "Power", railName[i], railData[i]); if(ret < 0) return ipmi::responseUnspecifiedError(); @@ -1740,6 +1740,21 @@ static std::optional getDIMMData(const nlohmann::json& js, const std::string& auto value = dimmData["Status_Reg"][regStr]; return static_cast(value.get()); } + else if (dataType == DataType::ERROR) { + auto err = static_cast(indexId); + std::string errStr; + + char hexStr[5]; + snprintf(hexStr, sizeof(hexStr), "0x%02x", static_cast(err)); + errStr = hexStr; + + if (!dimmData["Error_Code"].contains(errStr)) { + return std::nullopt; + } + + auto value = dimmData["Error_Code"][errStr]; + return static_cast(value.get()); + } } catch (std::exception& e) { return std::nullopt; } @@ -1748,7 +1763,7 @@ static std::optional getDIMMData(const nlohmann::json& js, const std::string& } /**************************************************************************** - reqId: 0:TS0 1:TS1 2:SPD_TEMP 3: Max Temp 4:Voltage 5:Current 6: Status Reg + reqId: 0:TS0 1:TS1 2:SPD_TEMP 3: Max Temp 4:Voltage 5:Current 6: Status Reg 7: Error Code *****************************************************************************/ ipmi::RspType> ipmiGetDimmTemp(uint8_t reqId) { @@ -1757,7 +1772,7 @@ ipmi::RspType> ipmiGetDimmTemp(uint8_t reqId) const nlohmann::json empty{}; nlohmann::json js; - if(reqId > 6) { + if(reqId > 7) { std::cout << "invalid reqId :" << (int)reqId << std::endl; return ipmi::responseParmOutOfRange(); } @@ -1806,7 +1821,8 @@ ipmi::RspType> ipmiGetDimmTemp(uint8_t reqId) + "_" + std::string(1, 'A' + i); std::optional temp, swa, swb, swc, swd, swe, swf; std::optional r4, r5, r6, r7, r8, r9, ra, rb; - + std::optional err_r32; + switch(static_cast(reqId)) { case ReqId::TS0: @@ -1847,6 +1863,11 @@ ipmi::RspType> ipmiGetDimmTemp(uint8_t reqId) ra = getDIMMData(js, dimmName, DataType::STATUS, StatusReg::REG_0A); rb = getDIMMData(js, dimmName, DataType::STATUS, StatusReg::REG_0B); break; + + case ReqId::ERROR_CODE: + err_r32 = getDIMMData(js, dimmName, DataType::ERROR, ErrCode::errCode_REG_32); + break; + default: std::cout << "invalid reqId :" << (int)reqId << std::endl; return ipmi::responseParmOutOfRange(); @@ -1865,6 +1886,11 @@ ipmi::RspType> ipmiGetDimmTemp(uint8_t reqId) byte_vector.push_back(opt.value_or(0xFF)); } } + else if(reqId == 7) { + for (const auto& opt : {err_r32}) { + byte_vector.push_back(opt.value_or(0xFF)); + } + } else { for (const auto& rail : {swa, swb, swc, swd, swe, swf}) { auto bytes = convertDoubleToTwoBytes(rail); diff --git a/meta-luxshare/meta-common/recipes-luxshare/ipmi-lux-oem/ipmi-oem/ipmi-oem.hpp b/meta-luxshare/meta-common/recipes-luxshare/ipmi-lux-oem/ipmi-oem/ipmi-oem.hpp index 33888627..3a756cd9 100755 --- a/meta-luxshare/meta-common/recipes-luxshare/ipmi-lux-oem/ipmi-oem/ipmi-oem.hpp +++ b/meta-luxshare/meta-common/recipes-luxshare/ipmi-lux-oem/ipmi-oem/ipmi-oem.hpp @@ -20,7 +20,8 @@ enum class DataType { CURRENT, POWER, VOLTAGE, - STATUS + STATUS, + ERROR }; enum class TempSensor { @@ -37,7 +38,8 @@ enum class ReqId { MAX_TEMP = 3, VOLTAGE = 4, CURRENT = 5, - STATUS_REG = 6 + STATUS_REG = 6, + ERROR_CODE = 7 }; enum class RailChannel { @@ -60,6 +62,10 @@ enum class StatusReg { REG_0B = 0x0B }; +enum class ErrCode { + errCode_REG_32 = 0x32 +}; + typedef struct { int8_t int_part; uint8_t frac_part;