Added support for ipmi tool based mux slot disable
Currently ipmitool doesn't support mctp mux-slot
disabling capablity.
this patch will support to disable/enable mctp
mux slot funtionality using ipmi tool.
Change-Id: I0bdbd86d2fb4f806d61f665a8014c0c097ee4258
Signed-off-by: Vasu V <vasu.v@intel.com>
diff --git a/include/manufacturingcommands.hpp b/include/manufacturingcommands.hpp
index 9ff69bf..07e0a5a 100644
--- a/include/manufacturingcommands.hpp
+++ b/include/manufacturingcommands.hpp
@@ -70,6 +70,17 @@
static constexpr const char* specialModeIntf =
"xyz.openbmc_project.Security.SpecialMode";
+static constexpr const char* mctpPcieSlotService =
+ "xyz.openbmc_project.MCTP_SMBus_PCIe_slot";
+static constexpr const char* mctpHsbpService =
+ "xyz.openbmc_project.MCTP_SMBus_HSBP";
+static constexpr const char* mctpObjPath = "/xyz/openbmc_project/mctp";
+static constexpr const char* mctpBaseIntf = "xyz.openbmc_project.MCTP.Base";
+
+constexpr const uint8_t slotNumMask = 0x0F;
+constexpr const uint8_t muxTypeMask = 0xF0;
+constexpr const uint8_t muxTypeShift = 4;
+
enum class SpecialMode : uint8_t
{
none = 0,
@@ -152,6 +163,17 @@
{
mctp = 0,
pcieScan,
+ mctpSlotSupport
+};
+
+enum SupportedFeatureMuxs : uint8_t
+{
+ pcieMuxSlot = 0,
+ pcieMcioMuxSlot,
+ pcieM2EdSffMuxSlot,
+ leftRaiserMuxSlot,
+ rightRaiserMuxSlot,
+ HsbpMuxSlot
};
enum SupportedFeatureActions : uint8_t
diff --git a/src/manufacturingcommands.cpp b/src/manufacturingcommands.cpp
index 3104c3e..cb55ee2 100644
--- a/src/manufacturingcommands.cpp
+++ b/src/manufacturingcommands.cpp
@@ -24,6 +24,7 @@
#include <phosphor-logging/lg2.hpp>
#include <types.hpp>
+#include <charconv>
#include <filesystem>
#include <fstream>
@@ -1438,6 +1439,108 @@
return ipmi::responseSuccess();
}
+static bool isNum(const std::string& s)
+{
+ if (s.empty())
+ {
+ return false;
+ }
+ uint8_t busNumber;
+ const auto sEnd = s.data() + s.size();
+ const auto& [ptr, ec] = std::from_chars(s.data(), sEnd, busNumber);
+ if (ec == std::errc() || ptr == sEnd)
+ {
+ return true;
+ }
+ return false;
+}
+
+bool getBusNumFromPath(const std::string& path, std::string& busStr)
+{
+ std::vector<std::string> parts;
+ boost::split(parts, path, boost::is_any_of("-"));
+ if (parts.size() == 2)
+ {
+ busStr = parts[1];
+ if (isNum(busStr))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+static ipmi::RspType<> muxSlotDisable(ipmi::Context::ptr& ctx,
+ std::string service, std::string muxName,
+ uint8_t action, uint8_t slotNum)
+{
+ boost::system::error_code ec;
+ const std::filesystem::path muxSymlinkDirPath =
+ "/dev/i2c-mux/" + muxName + "/Slot_" + std::to_string(slotNum + 1);
+ if (!std::filesystem::is_symlink(muxSymlinkDirPath))
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
+ std::string linkPath = std::filesystem::read_symlink(muxSymlinkDirPath);
+
+ std::string portNum;
+ if (!getBusNumFromPath(linkPath, portNum))
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
+ auto res = ctx->bus->yield_method_call<int>(
+ ctx->yield, ec, service, mctpObjPath, mctpBaseIntf, "SkipList",
+ std::vector<uint8_t>{action, static_cast<uint8_t>(std::stoi(portNum))});
+ if (ec)
+ {
+ lg2::error("Failed to set mctp skiplist");
+ return ipmi::responseUnspecifiedError();
+ }
+
+ if (!res)
+ {
+ return ipmi::responseResponseError();
+ }
+ return ipmi::responseSuccess();
+}
+
+static ipmi::RspType<> handleMCTPSlotFeature(ipmi::Context::ptr& ctx,
+ const uint8_t enable,
+ const uint8_t featureArg)
+{
+ uint8_t slotNum = (featureArg & slotNumMask);
+ switch ((featureArg & muxTypeMask) >> muxTypeShift)
+ {
+ case ipmi::SupportedFeatureMuxs::pcieMuxSlot:
+ return muxSlotDisable(ctx, mctpPcieSlotService, "PCIe_Mux", enable,
+ slotNum);
+ break;
+ case ipmi::SupportedFeatureMuxs::pcieMcioMuxSlot:
+ return muxSlotDisable(ctx, mctpPcieSlotService, "PCIe_MCIO_Mux",
+ enable, slotNum);
+ break;
+ case ipmi::SupportedFeatureMuxs::pcieM2EdSffMuxSlot:
+ return muxSlotDisable(ctx, mctpPcieSlotService, "M2_EDSFF_Mux",
+ enable, slotNum);
+ break;
+ case ipmi::SupportedFeatureMuxs::leftRaiserMuxSlot:
+ return muxSlotDisable(ctx, mctpPcieSlotService, "Left_Riser_Mux",
+ enable, slotNum);
+ break;
+ case ipmi::SupportedFeatureMuxs::rightRaiserMuxSlot:
+ return muxSlotDisable(ctx, mctpPcieSlotService, "Right_Riser_Mux",
+ enable, slotNum);
+ break;
+ case ipmi::SupportedFeatureMuxs::HsbpMuxSlot:
+ return muxSlotDisable(ctx, mctpHsbpService, "HSBP_Mux", enable,
+ slotNum);
+ break;
+ default:
+ lg2::warning("ERROR: Invalid Mux slot selected");
+ return ipmi::responseInvalidFieldRequest();
+ }
+}
+
/** @brief implements MTM BMC Feature Control IPMI command which can be
* used to enable or disable the supported BMC features.
* @param yield - context object that represents the currently executing
@@ -1483,6 +1586,9 @@
}
startOrStopService(ctx, enable, "xyz.openbmc_project.PCIe.service");
break;
+ case ipmi::SupportedFeatureControls::mctpSlotSupport:
+ return handleMCTPSlotFeature(ctx, enable, featureArg);
+ break;
default:
return ipmi::responseInvalidFieldRequest();
}