summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/errl/errlreasoncodes.H1
-rw-r--r--src/usr/errl/plugins/errludparserfactoryerrl.H2
-rw-r--r--src/usr/errl/plugins/errludwofdata.H206
-rw-r--r--src/usr/fapi2/plat_wof_access.C102
4 files changed, 294 insertions, 17 deletions
diff --git a/src/include/usr/errl/errlreasoncodes.H b/src/include/usr/errl/errlreasoncodes.H
index dfe0eb8fc..c77e1de2a 100644
--- a/src/include/usr/errl/errlreasoncodes.H
+++ b/src/include/usr/errl/errlreasoncodes.H
@@ -77,6 +77,7 @@ namespace ERRORLOG
ERRL_UDT_STRING_SET = 0x09,
ERRL_UDT_BUILD = 0x0A,
ERRL_UDT_SYSSTATE = 0x0B,
+ ERRL_UDT_WOFDATA = 0x0C,
};
// Identifiers for ERRL user data subsection versions
diff --git a/src/usr/errl/plugins/errludparserfactoryerrl.H b/src/usr/errl/plugins/errludparserfactoryerrl.H
index 923632852..fbefe231f 100644
--- a/src/usr/errl/plugins/errludparserfactoryerrl.H
+++ b/src/usr/errl/plugins/errludparserfactoryerrl.H
@@ -40,6 +40,7 @@
#include "errludsensor.H"
#include "errludbuild.H"
#include "errludstate.H"
+#include "errludwofdata.H"
namespace ERRORLOG
{
@@ -69,6 +70,7 @@ public:
registerParser<ErrlUserDetailsParserSensor>(ERRL_UDT_SENSOR);
registerParser<ErrlUserDetailsParserBuild>(ERRL_UDT_BUILD);
registerParser<ErrlUserDetailsParserSysState>(ERRL_UDT_SYSSTATE);
+ registerParser<ErrlUserDetailsParserWofData>(ERRL_UDT_WOFDATA);
}
private:
diff --git a/src/usr/errl/plugins/errludwofdata.H b/src/usr/errl/plugins/errludwofdata.H
new file mode 100644
index 000000000..f757c91d2
--- /dev/null
+++ b/src/usr/errl/plugins/errludwofdata.H
@@ -0,0 +1,206 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/errl/plugins/errludwofdata.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017,2018 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef ERRL_UDWOFDATA_H
+#define ERRL_UDWOFDATA_H
+
+/**
+ * @file errludwofdata.H
+ *
+ * Defines the ErrlUserDetailsWofData class that parses the
+ * WOF data user detail section of an error log
+ */
+
+#include "errluserdetails.H"
+#include <targeting/common/target.H>
+
+namespace ERRORLOG
+{
+
+/**
+ * @class ErrlUserDetailsParserWofData
+ *
+ * Parses WOF data user detail in an error log
+ */
+class ErrlUserDetailsParserWofData :public ErrlUserDetailsParser
+{
+public:
+ /**
+ * @brief Constructor
+ */
+ ErrlUserDetailsParserWofData() {}
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~ErrlUserDetailsParserWofData() {}
+
+ /**
+ * @brief Parses WOF detail data from an error log
+ *
+ * @param i_version Version of the data
+ * @param i_parser ErrlUsrParser object for outputting information
+ * @param i_pBuffer Pointer to buffer containing WOF detail data
+ * @param i_buflen Length of the buffer
+ */
+ virtual void parse(errlver_t i_version,
+ ErrlUsrParser & i_parser,
+ void * i_pBuffer,
+ const uint32_t i_buflen) const
+ {
+ // From src/usr/fapi2/plat_wof_access.C
+ typedef struct
+ {
+ uint8_t core_count;
+ uint8_t mode;
+ uint16_t socket_power_w;
+ uint16_t sort_power_freq_mhz;
+ } wofTableCompareData_t;
+
+ // From src/import/chips/p9/procedures/hwp/lib/p9_pstates_common.h
+ typedef enum
+ {
+ WOF_MODE_UNKNOWN = 0,
+ WOF_MODE_NOMINAL = 1,
+ WOF_MODE_TURBO = 2
+ } WOF_MODE;
+
+ uint16_t tableEntries = 0;
+
+ // Format of WofData error buffer:
+ // uint16_t - # of table entries (including search for table)
+ // wofTableCompareData_t - Searched for this table
+ // wofTableCompareData_t - last table rejected for possible match
+ // ...
+ // wofTableCompareData_t - 1st table rejected for possible match
+ // NOTE: format must match
+ // addWofCompareDataToErrl() in plat_wof_access.C
+ if ((NULL != i_pBuffer) && (i_buflen >= sizeof(tableEntries)))
+ {
+ tableEntries = ntohs(*(reinterpret_cast<uint16_t*>(i_pBuffer)));
+ }
+
+ // How many entries are really present in this buffer?
+ uint16_t actualTableCount = (i_buflen - sizeof(tableEntries)) /
+ sizeof(wofTableCompareData_t);
+
+ // sanity check to verify we are getting all the table data
+ if (tableEntries != actualTableCount)
+ {
+ i_parser.PrintString("**************************************","");
+ i_parser.PrintNumber("Total entries calculated", "%d",
+ actualTableCount);
+ i_parser.PrintNumber("Total entries expected", "%d",
+ tableEntries);
+ i_parser.PrintString("**************************************","");
+
+ tableEntries = actualTableCount; // don't go over buffer length
+ }
+
+ // Check that the remaining data breaks down into parsable
+ // wofTableCompareData_t entries
+ if ( (i_buflen - sizeof(tableEntries))
+ % sizeof(wofTableCompareData_t) == 0 )
+ {
+ i_parser.PrintString("---------------------------------------",
+ "---------------------------------------");
+ i_parser.PrintNumber("Total WOF Tables compared", "%d",
+ tableEntries-1);
+
+ // point to start of table compare data
+ void * i_pTableData = (uint8_t*)i_pBuffer + sizeof(tableEntries);
+ wofTableCompareData_t* outputDataPtr =
+ static_cast<wofTableCompareData_t*>(i_pTableData);
+ for ( uint32_t tableEntry = 0; tableEntry < tableEntries;
+ ++tableEntry )
+ {
+ if (tableEntry == 0)
+ {
+ i_parser.PrintString("---------------------------------------",
+ "---------------------------------------");
+ i_parser.PrintString("Searched for this table",
+ "Tried to match this:");
+ }
+ else
+ {
+ i_parser.PrintString("---------------------------------------",
+ "---------------------------");
+ i_parser.PrintNumber("WOF Table", "#%d", tableEntry);
+ }
+
+ i_parser.PrintNumber( "Core Count", "%d",
+ outputDataPtr->core_count );
+
+ switch(outputDataPtr->mode)
+ {
+ case WOF_MODE_UNKNOWN:
+ {
+ i_parser.PrintString( "Mode", "Any" );
+ break;
+ }
+ case WOF_MODE_NOMINAL:
+ {
+ i_parser.PrintString( "Mode", "Nominal" );
+ break;
+ }
+ case WOF_MODE_TURBO:
+ {
+ i_parser.PrintString( "Mode", "Turbo" );
+ break;
+ }
+ default:
+ {
+ i_parser.PrintNumber( "Mode", "UNKNOWN: 0x%X",
+ outputDataPtr->mode );
+ break;
+ }
+ }
+ i_parser.PrintNumber("Socket Power (Watts)", "%d",
+ ntohs(outputDataPtr->socket_power_w));
+ i_parser.PrintNumber("Sort Power Freq (MHz)", "%d",
+ ntohs(outputDataPtr->sort_power_freq_mhz));
+ outputDataPtr++; // go to next table entry
+ }
+ }
+ else
+ {
+ i_parser.PrintNumber("WOF Buffer length", "0x%X", i_buflen);
+ i_parser.PrintString("Expected buffer format:",
+ "uint16_t count, match this entry, unmatched entries");
+ i_parser.PrintNumber("Each entry size", "%d",
+ sizeof(wofTableCompareData_t));
+ i_parser.PrintHexDump(i_pBuffer, i_buflen);
+ }
+ }
+
+private:
+ // Disabled
+ ErrlUserDetailsParserWofData(const ErrlUserDetailsParserWofData &);
+ ErrlUserDetailsParserWofData & operator=(
+ const ErrlUserDetailsParserWofData &);
+};
+
+}
+
+#endif
diff --git a/src/usr/fapi2/plat_wof_access.C b/src/usr/fapi2/plat_wof_access.C
index fc8ce7cc9..24c17b8aa 100644
--- a/src/usr/fapi2/plat_wof_access.C
+++ b/src/usr/fapi2/plat_wof_access.C
@@ -108,6 +108,72 @@ typedef struct __attribute__((__packed__)) wofSectionTableEntry
} wofSectionTableEntry_t;
+// Compared fields in each WOF table header entry
+// NOTE: struct must match errl/plugins/errludwofdata.H
+typedef struct __attribute__((__packed__)) wofTableCompareData
+{
+ uint8_t core_count;
+ uint8_t mode;
+ uint16_t socket_power_w;
+ uint16_t sort_power_freq_mhz;
+} wofTableCompareData_t;
+
+/**
+ * @brief Adds WOF detail data to an error log
+ *
+ * Format of WofData error buffer:
+ * uint16_t - # of table entries (including search for table)
+ * wofTableCompareData_t - Searched for this table
+ * wofTableCompareData_t - last table rejected for possible match
+ * ...
+ * wofTableCompareData_t - 1st table rejected for possible match
+ * NOTE: format must match errl plugin parser (errludwofdata.H)
+ *
+ * @param io_err Error log to add data into
+ * @param i_match_data Searched for table data
+ * @param i_headers Table headers searched that did not match
+ */
+void addWofCompareDataToErrl( errlHndl_t &io_err,
+ wofTableCompareData_t * i_match_data,
+ std::vector<WofTablesHeader_t*> i_headers )
+{
+ uint16_t l_WOFentries = i_headers.size() + 1; // add searched entry too
+
+ // Allocate WofData error buffer
+ uint32_t l_data_len = sizeof(l_WOFentries) +
+ l_WOFentries * sizeof(WofTablesHeader_t);
+ uint8_t * l_data = new uint8_t[l_data_len];
+
+ wofTableCompareData_t * l_tableDataPtr =
+ reinterpret_cast<wofTableCompareData_t*>(l_data + sizeof(l_WOFentries));
+
+ // first table entry is the data we tried to match
+ l_tableDataPtr[0] = *i_match_data;
+ l_tableDataPtr++;
+
+ // add all the non-matched WOF data header sections
+ while(i_headers.size())
+ {
+ WofTablesHeader_t * tmpHeader = i_headers.back();
+ l_tableDataPtr->core_count = tmpHeader->core_count;
+ l_tableDataPtr->mode = tmpHeader->mode;
+ l_tableDataPtr->socket_power_w = tmpHeader->socket_power_w;
+ l_tableDataPtr->sort_power_freq_mhz = tmpHeader->sort_power_freq_mhz;
+ l_tableDataPtr++;
+ i_headers.pop_back();
+ }
+
+ io_err->addFFDC(
+ ERRL_COMP_ID,
+ l_data,
+ l_data_len,
+ 0, // version
+ ERRORLOG::ERRL_UDT_WOFDATA, // WOF DATA parser
+ false ); // merge
+
+ delete [] l_data;
+}
+
fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData)
{
FAPI_DBG("Entering platParseWOFTables ....");
@@ -450,6 +516,8 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData)
{
// Found a match
FAPI_INF("Found a WOF table match");
+ FAPI_INF("core_count: %d, socket power w: %d, sort power freq MHz: %d, ver: %d, mode: %d",
+ l_numCores, l_socketPower, l_sortFreq, l_ver, l_mode);
// Copy the WOF table to the output pointer
memcpy(o_wofData,
@@ -511,10 +579,10 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData)
* @moduleid fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES
* @reasoncode fapi2::RC_WOF_TABLE_NOT_FOUND
* @userdata1[00:15] Number of cores
- * @userdata1[16:31] WOF Power Mode (0=Nominal,1=Turbo)
+ * @userdata1[16:31] WOF Power Mode (1=Nominal, 2=Turbo)
* @userdata1[32:63] Socket power
- * @userdata2[00:31] Nest frequency
- * @userdata2[32:63] Sort frequency
+ * @userdata2[00:31] Sort frequency
+ * @userdata2[32:63] Number of WOF tables checked
* @devdesc No WOF table match found
* @custdesc Firmware Error
*/
@@ -524,11 +592,11 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData)
fapi2::RC_WOF_TABLE_NOT_FOUND,
TWO_UINT16_ONE_UINT32_TO_UINT64(
l_numCores,
- l_wofPowerLimit,
+ l_mode,
l_socketPower),
TWO_UINT32_TO_UINT64(
- l_nestFreq,
- l_sortFreq),
+ l_sortFreq,
+ l_headers.size()),
true); //software callout
l_errl->collectTrace(FAPI_TRACE_NAME);
@@ -537,17 +605,17 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData)
l_sys,
TARGETING::ATTR_WOF_TABLE_LID_NUMBER)
.addToLog(l_errl);
- while(l_headers.size())
- {
- l_errl->addFFDC(
- HWPF_COMP_ID,
- l_headers.back(),
- sizeof(WofTablesHeader_t),
- 0, // version
- ERRORLOG::ERRL_UDT_NOFORMAT, // parser ignores data
- false ); // merge
- l_headers.pop_back();
- }
+
+ // Add table data to error log as own section
+ // Add just the compare fields into the error log
+ // for each WofTable that did not match
+ wofTableCompareData_t l_match_data_fields;
+ l_match_data_fields.core_count = l_numCores;
+ l_match_data_fields.socket_power_w = l_socketPower;
+ l_match_data_fields.sort_power_freq_mhz = l_sortFreq;
+ l_match_data_fields.mode = l_mode;
+
+ addWofCompareDataToErrl(l_errl, &l_match_data_fields, l_headers);
l_rc.setPlatDataPtr(reinterpret_cast<void *>(l_errl));
break;
OpenPOWER on IntegriCloud