diff options
-rw-r--r-- | Redfish.md | 4 | ||||
-rw-r--r-- | redfish-core/lib/pcie.hpp | 198 |
2 files changed, 178 insertions, 24 deletions
diff --git a/Redfish.md b/Redfish.md index 347048dd5f..a7b3445d82 100644 --- a/Redfish.md +++ b/Redfish.md @@ -863,6 +863,10 @@ other. - LanesInUse - PCIeType - SerialNumber +- Slot + - Lanes + - PCIeType + - SlotType - SparePartNumber - Status diff --git a/redfish-core/lib/pcie.hpp b/redfish-core/lib/pcie.hpp index 82e1a5f1a6..e10ba64643 100644 --- a/redfish-core/lib/pcie.hpp +++ b/redfish-core/lib/pcie.hpp @@ -35,6 +35,8 @@ namespace redfish static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory"; static constexpr std::array<std::string_view, 1> pcieDeviceInterface = { "xyz.openbmc_project.Inventory.Item.PCIeDevice"}; +static constexpr std::array<std::string_view, 1> pcieSlotInterface = { + "xyz.openbmc_project.Inventory.Item.PCIeSlot"}; static inline void handlePCIeDevicePath( const std::string& pcieDeviceId, @@ -146,6 +148,148 @@ inline void requestRoutesSystemPCIeDeviceCollection(App& app) std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app))); } +inline void addPCIeSlotProperties( + crow::Response& res, const boost::system::error_code& ec, + const dbus::utility::DBusPropertiesMap& pcieSlotProperties) +{ + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error for getAllProperties" + << ec.value(); + messages::internalError(res); + return; + } + std::string generation; + size_t lanes = 0; + std::string slotType; + + bool success = sdbusplus::unpackPropertiesNoThrow( + dbus_utils::UnpackErrorPrinter(), pcieSlotProperties, "Generation", + generation, "Lanes", lanes, "SlotType", slotType); + + if (!success) + { + messages::internalError(res); + return; + } + + std::optional<pcie_device::PCIeTypes> pcieType = + pcie_util::redfishPcieGenerationFromDbus(generation); + if (!pcieType) + { + BMCWEB_LOG_WARNING << "Unknown PCIeType: " << generation; + } + else + { + if (*pcieType == pcie_device::PCIeTypes::Invalid) + { + BMCWEB_LOG_ERROR << "Invalid PCIeType: " << generation; + messages::internalError(res); + return; + } + res.jsonValue["Slot"]["PCIeType"] = *pcieType; + } + + res.jsonValue["Slot"]["Lanes"] = lanes; + + std::optional<pcie_slots::SlotTypes> redfishSlotType = + pcie_util::dbusSlotTypeToRf(slotType); + if (!redfishSlotType) + { + BMCWEB_LOG_WARNING << "Unknown PCIeSlot Type: " << slotType; + } + else + { + if (*redfishSlotType == pcie_slots::SlotTypes::Invalid) + { + BMCWEB_LOG_ERROR << "Invalid PCIeSlot type: " << slotType; + messages::internalError(res); + return; + } + res.jsonValue["Slot"]["SlotType"] = *redfishSlotType; + } +} + +inline void getPCIeDeviceSlotPath( + const std::string& pcieDevicePath, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + std::function<void(const std::string& pcieDeviceSlot)>&& callback) +{ + std::string associationPath = pcieDevicePath + "/contained_by"; + dbus::utility::getAssociatedSubTreePaths( + associationPath, sdbusplus::message::object_path(inventoryPath), 0, + pcieSlotInterface, + [callback, asyncResp, pcieDevicePath]( + const boost::system::error_code& ec, + const dbus::utility::MapperGetSubTreePathsResponse& endpoints) { + if (ec) + { + if (ec.value() == EBADR) + { + // Missing association is not an error + return; + } + BMCWEB_LOG_ERROR + << "DBUS response error for getAssociatedSubTreePaths " + << ec.value(); + messages::internalError(asyncResp->res); + return; + } + if (endpoints.size() > 1) + { + BMCWEB_LOG_ERROR + << "PCIeDevice is associated with more than one PCIeSlot: " + << endpoints.size(); + messages::internalError(asyncResp->res); + return; + } + if (endpoints.empty()) + { + // If the device doesn't have an association, return without PCIe + // Slot properties + BMCWEB_LOG_DEBUG << "PCIeDevice is not associated with PCIeSlot"; + return; + } + callback(endpoints[0]); + }); +} + +inline void + afterGetDbusObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& pcieDeviceSlot, + const boost::system::error_code& ec, + const dbus::utility::MapperGetObject& object) +{ + if (ec || object.empty()) + { + BMCWEB_LOG_ERROR << "DBUS response error for getDbusObject " + << ec.value(); + messages::internalError(asyncResp->res); + return; + } + sdbusplus::asio::getAllProperties( + *crow::connections::systemBus, object.begin()->first, pcieDeviceSlot, + "xyz.openbmc_project.Inventory.Item.PCIeSlot", + [asyncResp]( + const boost::system::error_code& ec2, + const dbus::utility::DBusPropertiesMap& pcieSlotProperties) { + addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties); + }); +} + +inline void afterGetPCIeDeviceSlotPath( + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& pcieDeviceSlot) +{ + dbus::utility::getDbusObject( + pcieDeviceSlot, pcieSlotInterface, + [asyncResp, + pcieDeviceSlot](const boost::system::error_code& ec, + const dbus::utility::MapperGetObject& object) { + afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object); + }); +} + inline void getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& pcieDevicePath, @@ -181,7 +325,7 @@ inline void sdbusplus::asio::getProperty<bool>( *crow::connections::systemBus, service, pcieDevicePath, "xyz.openbmc_project.Inventory.Item", "Present", - [asyncResp](const boost::system::error_code& ec, const bool value) { + [asyncResp](const boost::system::error_code& ec, bool value) { if (ec) { if (ec.value() != EBADR) @@ -265,7 +409,8 @@ inline void } inline void addPCIeDeviceProperties( - crow::Response& resp, const std::string& pcieDeviceId, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& pcieDeviceId, const dbus::utility::DBusPropertiesMap& pcieDevProperties) { const std::string* deviceType = nullptr; @@ -279,13 +424,13 @@ inline void addPCIeDeviceProperties( if (!success) { - messages::internalError(resp); + messages::internalError(asyncResp->res); return; } if (deviceType != nullptr && !deviceType->empty()) { - resp.jsonValue["PCIeInterface"]["DeviceType"] = *deviceType; + asyncResp->res.jsonValue["PCIeInterface"]["DeviceType"] = *deviceType; } if (generationInUse != nullptr) @@ -304,10 +449,10 @@ inline void addPCIeDeviceProperties( { BMCWEB_LOG_ERROR << "Invalid PCIe Device Generation: " << *generationInUse; - messages::internalError(resp); + messages::internalError(asyncResp->res); return; } - resp.jsonValue["PCIeInterface"]["PCIeType"] = + asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] = *redfishGenerationInUse; } } @@ -316,12 +461,13 @@ inline void addPCIeDeviceProperties( // left as off if it is a default value. if (lanesInUse != nullptr && *lanesInUse != 0) { - resp.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse; + asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse; } - resp.jsonValue["PCIeFunctions"]["@odata.id"] = boost::urls::format( - "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions", - pcieDeviceId); + asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] = + boost::urls::format( + "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions", + pcieDeviceId); } inline void getPCIeDeviceProperties( @@ -365,6 +511,23 @@ inline void addPCIeDeviceCommonProperties( asyncResp->res.jsonValue["Status"]["Health"] = "OK"; } +inline void afterGetValidPcieDevicePath( + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& pcieDeviceId, const std::string& pcieDevicePath, + const std::string& service) +{ + addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId); + getPCIeDeviceAsset(asyncResp, pcieDevicePath, service); + getPCIeDeviceState(asyncResp, pcieDevicePath, service); + getPCIeDeviceHealth(asyncResp, pcieDevicePath, service); + getPCIeDeviceProperties( + asyncResp, pcieDevicePath, service, + std::bind_front(addPCIeDeviceProperties, asyncResp, pcieDeviceId)); + getPCIeDeviceSlotPath( + pcieDevicePath, asyncResp, + std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp)); +} + inline void handlePCIeDeviceGet(App& app, const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, @@ -391,20 +554,7 @@ inline void getValidPCIeDevicePath( pcieDeviceId, asyncResp, - [asyncResp, pcieDeviceId](const std::string& pcieDevicePath, - const std::string& service) { - addPCIeDeviceCommonProperties(asyncResp, pcieDeviceId); - getPCIeDeviceAsset(asyncResp, pcieDevicePath, service); - getPCIeDeviceState(asyncResp, pcieDevicePath, service); - getPCIeDeviceHealth(asyncResp, pcieDevicePath, service); - getPCIeDeviceProperties( - asyncResp, pcieDevicePath, service, - [asyncResp, pcieDeviceId]( - const dbus::utility::DBusPropertiesMap& pcieDevProperties) { - addPCIeDeviceProperties(asyncResp->res, pcieDeviceId, - pcieDevProperties); - }); - }); + std::bind_front(afterGetValidPcieDevicePath, asyncResp, pcieDeviceId)); } inline void requestRoutesSystemPCIeDevice(App& app) |