Bus callout resolution support
Change-Id: I516d151350ac0d2342c966266f2e90bae8572c37
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
diff --git a/analyzer/ras-data/data/ras-data-explorer-11.json b/analyzer/ras-data/data/ras-data-explorer-11.json
index 37a216e..9f638da 100644
--- a/analyzer/ras-data/data/ras-data-explorer-11.json
+++ b/analyzer/ras-data/data/ras-data-explorer-11.json
@@ -51,9 +51,21 @@
],
"omi_bus" : [
{
- "type" : "callout_bus",
- "name" : "omi_bus",
- "guard" : true
+ "type" : "callout_self",
+ "priority" : "MED_A",
+ "guard" : true
+ },
+ {
+ "type" : "callout_connected",
+ "name" : "omi_bus",
+ "priority" : "MED_A",
+ "guard" : true
+ },
+ {
+ "type" : "callout_bus",
+ "name" : "omi_bus",
+ "priority" : "LOW",
+ "guard" : false
}
],
"level2_M_self_L" : [
diff --git a/analyzer/ras-data/data/ras-data-explorer-20.json b/analyzer/ras-data/data/ras-data-explorer-20.json
index 1d99c6a..354106f 100644
--- a/analyzer/ras-data/data/ras-data-explorer-20.json
+++ b/analyzer/ras-data/data/ras-data-explorer-20.json
@@ -51,9 +51,21 @@
],
"omi_bus" : [
{
- "type" : "callout_bus",
- "name" : "omi_bus",
- "guard" : true
+ "type" : "callout_self",
+ "priority" : "MED_A",
+ "guard" : true
+ },
+ {
+ "type" : "callout_connected",
+ "name" : "omi_bus",
+ "priority" : "MED_A",
+ "guard" : true
+ },
+ {
+ "type" : "callout_bus",
+ "name" : "omi_bus",
+ "priority" : "LOW",
+ "guard" : false
}
],
"level2_M_self_L" : [
diff --git a/analyzer/ras-data/ras-data-definition.md b/analyzer/ras-data/ras-data-definition.md
index 2df571b..d27b3ab 100644
--- a/analyzer/ras-data/ras-data-definition.md
+++ b/analyzer/ras-data/ras-data-definition.md
@@ -147,22 +147,20 @@
#### 5.1.5) action type `callout_bus`
This will request to callout all parts associated with a bus (RX/TX endpoints
-and everything else in between the endpoints). Bus callouts have very specific
-priority:
+and everything else in between the endpoints). All parts will be called out with
+the same priority. If a particular part, like the endpoints, need to be called
+out at a different priority, they will need to be called out using a different
+action type. For example:
-- If an SMP cable exists, callout the cable with priority `HIGH`.
-- Callout both RX and TX endpoints with priority `MED_A`.
-- Callout everything else in between with priority `LOW`.
-
-In some special cases, the callout priority of the endpoints may differ from the
-default `MED_A`. In which case, the optional priority properties can be used.
+- `callout_self` with priority `MED_A`. (RX endpoint MED_A)
+- `callout_connected` with priority `MED_A`. (TX endpoint MED_A)
+- `callout_bus` with priority `LOW`. (everything else LOW)
| Keyword | Description |
|-------------|----------------------------------------------------------------|
| type | value (string): `callout_bus` |
| name | The `<bus_name>` as defined by the `buses` keyword. |
-| rx_priority | Optional priority of the receiving side endpoint |
-| tx_priority | Optional priority of the transfer side endpoint |
+| priority | See `priority` table above. |
| guard | See `guard` table above. |
#### 5.1.6) action type `callout_clock`
diff --git a/analyzer/ras-data/ras-data-parser.cpp b/analyzer/ras-data/ras-data-parser.cpp
index ea59c07..6ec8b6c 100644
--- a/analyzer/ras-data/ras-data-parser.cpp
+++ b/analyzer/ras-data/ras-data-parser.cpp
@@ -203,14 +203,15 @@
}
else if ("callout_bus" == type)
{
- auto name = a.at("name").get<std::string>();
- // auto rx_priority = a.at("rx_priority").get<std::string>();
- // auto tx_priority = a.at("tx_priority").get<std::string>();
- auto guard = a.at("guard").get<bool>();
+ auto name = a.at("name").get<std::string>();
+ auto priority = a.at("priority").get<std::string>();
+ auto guard = a.at("guard").get<bool>();
- // TODO
- trace::inf("callout_bus: name=%s guard=%c", name.c_str(),
- guard ? 'T' : 'F');
+ auto busData = parseBus(i_data, name);
+
+ o_list->push(std::make_shared<BusCalloutResolution>(
+ std::get<0>(busData), std::get<1>(busData),
+ getPriority(priority), guard));
}
else if ("callout_clock" == type)
{
diff --git a/analyzer/ras-data/schema/ras-data-schema-v01.json b/analyzer/ras-data/schema/ras-data-schema-v01.json
index d675631..10f03ea 100644
--- a/analyzer/ras-data/schema/ras-data-schema-v01.json
+++ b/analyzer/ras-data/schema/ras-data-schema-v01.json
@@ -143,11 +143,7 @@
}
},
"then": {
- "required": [ "name", "guard" ],
- "not": { "required": [ "priority" ] },
- "properties": {
- "rx_priority": { "$ref": "#/definitions/priority" },
- "tx_priority": { "$ref": "#/definitions/priority" }
+ "required": [ "name", "priority", "guard" ],
}
}
},
diff --git a/analyzer/resolution.cpp b/analyzer/resolution.cpp
index d6cd174..86a10e1 100644
--- a/analyzer/resolution.cpp
+++ b/analyzer/resolution.cpp
@@ -176,6 +176,62 @@
//------------------------------------------------------------------------------
+void BusCalloutResolution::resolve(ServiceData& io_sd) const
+{
+ // Get the chip target from the root cause signature.
+ auto chipTarget = __getRootCauseChipTarget(io_sd);
+
+ // Get the endpoint target for the receiving side of the bus.
+ auto rxTarget = __getUnitTarget(chipTarget, iv_unitPath);
+
+ // Get the endpoint target for the transfer side of the bus.
+ auto txTarget = __getConnectedTarget(rxTarget, iv_busType);
+
+ // Callout the RX endpoint.
+ nlohmann::json rxCallout;
+ rxCallout["LocationCode"] = util::pdbg::getLocationCode(rxTarget);
+ rxCallout["Priority"] = iv_priority.getUserDataString();
+ io_sd.addCallout(rxCallout);
+
+ // Callout the TX endpoint.
+ nlohmann::json txCallout;
+ txCallout["LocationCode"] = util::pdbg::getLocationCode(txTarget);
+ txCallout["Priority"] = iv_priority.getUserDataString();
+ io_sd.addCallout(txCallout);
+
+ // Callout everything else in between.
+ // TODO: For P10 (OMI bus and XBUS), the callout is simply the backplane.
+ // There isn't a devtree object for this, yet. So will need to
+ // hardcode the location code for now. In the future, we will need a
+ // mechanism to make this data driven.
+ nlohmann::json bpCallout;
+ bpCallout["LocationCode"] = "P0";
+ bpCallout["Priority"] = iv_priority.getUserDataString();
+ io_sd.addCallout(bpCallout);
+
+ // Guard the RX endpoint.
+ Guard guard =
+ io_sd.addGuard(util::pdbg::getPhysDevPath(rxTarget), iv_guard);
+
+ // Guard the TX endpoint.
+ // No need to check return because it is the same as RX target.
+ io_sd.addGuard(util::pdbg::getPhysDevPath(txTarget), iv_guard);
+
+ // TODO: Currently no guard for "everything else in between".
+
+ // Add the callout FFDC to the service data.
+ nlohmann::json ffdc;
+ ffdc["Callout Type"] = "Bus Callout";
+ ffdc["Bus Type"] = iv_busType.getString();
+ ffdc["RX Target"] = util::pdbg::getPhysDevPath(rxTarget);
+ ffdc["TX Target"] = util::pdbg::getPhysDevPath(txTarget);
+ ffdc["Priority"] = iv_priority.getRegistryString();
+ ffdc["Guard Type"] = guard.getString();
+ io_sd.addCalloutFFDC(ffdc);
+}
+
+//------------------------------------------------------------------------------
+
void ClockCalloutResolution::resolve(ServiceData& io_sd) const
{
// Add the callout to the service data.
diff --git a/analyzer/resolution.hpp b/analyzer/resolution.hpp
index aee3851..9530b70 100644
--- a/analyzer/resolution.hpp
+++ b/analyzer/resolution.hpp
@@ -97,6 +97,48 @@
void resolve(ServiceData& io_sd) const override;
};
+/**
+ * @brief Resolution to callout all parts on a bus (RX/TX endpoints and
+ * everything else in between).
+ */
+class BusCalloutResolution : public Resolution
+{
+ public:
+ /**
+ * @brief Constructor from components.
+ * @param i_busType The bus type.
+ * @param i_unitPath The path of the chip unit that is connected to the
+ * other chip. An empty string refers to the chip itself,
+ * which generally means this chip is a child of another.
+ * @param i_priority The callout priority.
+ * @param i_guard The guard type for this callout.
+ */
+ BusCalloutResolution(const callout::BusType& i_busType,
+ const std::string& i_unitPath,
+ const callout::Priority& i_priority, bool i_guard) :
+ iv_busType(i_busType),
+ iv_unitPath(i_unitPath), iv_priority(i_priority), iv_guard(i_guard)
+ {}
+
+ private:
+ /** The bus type. */
+ const callout::BusType iv_busType;
+
+ /** The devtree path the chip unit that is connected to the other chip. An
+ * empty string refers to the chip itself, which generally means this chip
+ * is a child of the other chip. */
+ const std::string iv_unitPath;
+
+ /** The callout priority. */
+ const callout::Priority iv_priority;
+
+ /** True, if guard is required. False, otherwise. */
+ const bool iv_guard;
+
+ public:
+ void resolve(ServiceData& io_sd) const override;
+};
+
/** @brief Resolves a clock callout service event. */
class ClockCalloutResolution : public Resolution
{
diff --git a/test/resolution_test.cpp b/test/resolution_test.cpp
index d50213d..24a5213 100644
--- a/test/resolution_test.cpp
+++ b/test/resolution_test.cpp
@@ -155,6 +155,61 @@
//------------------------------------------------------------------------------
+void BusCalloutResolution::resolve(ServiceData& io_sd) const
+{
+ // Get the chip target path from the root cause signature.
+ auto chipPath = __getRootCauseChipPath(io_sd);
+
+ // Get the endpoint target path for the receiving side of the bus.
+ auto rxPath = __getUnitPath(chipPath, iv_unitPath);
+
+ // Get the endpoint target path for the transfer side of the bus.
+ auto txPath = __getConnectedPath(rxPath, iv_busType);
+
+ // Callout the RX endpoint.
+ nlohmann::json rxCallout;
+ rxCallout["LocationCode"] = chipPath;
+ rxCallout["Priority"] = iv_priority.getUserDataString();
+ io_sd.addCallout(rxCallout);
+
+ // Callout the TX endpoint.
+ nlohmann::json txCallout;
+ txCallout["LocationCode"] = std::get<1>(txPath);
+ txCallout["Priority"] = iv_priority.getUserDataString();
+ io_sd.addCallout(txCallout);
+
+ // Callout everything else in between.
+ // TODO: For P10 (OMI bus and XBUS), the callout is simply the backplane.
+ // There isn't a devtree object for this, yet. So will need to
+ // hardcode the location code for now. In the future, we will need a
+ // mechanism to make this data driven.
+ nlohmann::json bpCallout;
+ bpCallout["LocationCode"] = "P0";
+ bpCallout["Priority"] = iv_priority.getUserDataString();
+ io_sd.addCallout(bpCallout);
+
+ // Guard the RX endpoint.
+ Guard guard = io_sd.addGuard(rxPath, iv_guard);
+
+ // Guard the TX endpoint.
+ // No need to check return because it is the same as RX target.
+ io_sd.addGuard(std::get<0>(txPath), iv_guard);
+
+ // TODO: Currently no guard for "everything else in between".
+
+ // Add the callout FFDC to the service data.
+ nlohmann::json ffdc;
+ ffdc["Callout Type"] = "Bus Callout";
+ ffdc["Bus Type"] = iv_busType.getString();
+ ffdc["RX Target"] = rxPath;
+ ffdc["TX Target"] = std::get<0>(txPath);
+ ffdc["Priority"] = iv_priority.getRegistryString();
+ ffdc["Guard Type"] = guard.getString();
+ io_sd.addCalloutFFDC(ffdc);
+}
+
+//------------------------------------------------------------------------------
+
void ProcedureCalloutResolution::resolve(ServiceData& io_sd) const
{
// Add the actual callout to the service data.
@@ -393,6 +448,74 @@
EXPECT_EQ(s, j.dump(4));
}
+TEST(Resolution, BusCallout)
+{
+ auto c1 = std::make_shared<HardwareCalloutResolution>(
+ omi_str, callout::Priority::MED_A, true);
+
+ auto c2 = std::make_shared<ConnectedCalloutResolution>(
+ callout::BusType::OMI_BUS, omi_str, callout::Priority::MED_A, true);
+
+ auto c3 = std::make_shared<BusCalloutResolution>(
+ callout::BusType::OMI_BUS, omi_str, callout::Priority::LOW, false);
+
+ libhei::Chip chip{chip_str, 0xdeadbeef};
+ libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
+ ServiceData sd{sig, true};
+
+ nlohmann::json j{};
+ std::string s{};
+
+ c1->resolve(sd);
+ c2->resolve(sd);
+ c3->resolve(sd);
+
+ // Callout list
+ j = sd.getCalloutList();
+ s = R"([
+ {
+ "LocationCode": "/proc0",
+ "Priority": "A"
+ },
+ {
+ "LocationCode": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0",
+ "Priority": "A"
+ },
+ {
+ "LocationCode": "P0",
+ "Priority": "L"
+ }
+])";
+ EXPECT_EQ(s, j.dump(4));
+
+ // Callout FFDC
+ j = sd.getCalloutFFDC();
+ s = R"([
+ {
+ "Callout Type": "Hardware Callout",
+ "Guard Type": "FATAL",
+ "Priority": "medium_group_A",
+ "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0"
+ },
+ {
+ "Bus Type": "OMI_BUS",
+ "Callout Type": "Connected Callout",
+ "Guard Type": "FATAL",
+ "Priority": "medium_group_A",
+ "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0"
+ },
+ {
+ "Bus Type": "OMI_BUS",
+ "Callout Type": "Bus Callout",
+ "Guard Type": "NONE",
+ "Priority": "low",
+ "RX Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0",
+ "TX Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0"
+ }
+])";
+ EXPECT_EQ(s, j.dump(4));
+}
+
TEST(Resolution, ClockCallout)
{
auto c1 = std::make_shared<ClockCalloutResolution>(