summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Feist <james.feist@linux.intel.com>2019-10-17 00:36:58 +0300
committerFeist, James <james.feist@intel.com>2019-10-22 20:52:05 +0300
commit29c10072c157687c8bce0e9bf63cad87310e71fe (patch)
tree9819df4c96702300f13079dd9ef6a59f218ef0f5
parent30110fe5b18999bddc5721dc5611f542f6feeabd (diff)
downloadprovingground-29c10072c157687c8bce0e9bf63cad87310e71fe.tar.xz
Make hsbp-manager expose all redfish properties
Hsbp manager needs to query entity-manager for nvme fields to populate all driver interfaces. This is needed so indexing works correctly. This also exposes all M.2 drive interfaces at the end of the hsbp range. This allows correct numbering. When we find a drive in entity-manager, we backtrack from the virtual bus on the mux, to find out what bus the mux is on, this tells us the hsbp. We then use the virtual bus to identify the channel, this tells us the drive index. Tested: Saw 9 drives with a 1 hsbp and 1 M.2 configuration Change-Id: I8e730a6a4229b3816991c629439ed4639710d114 Signed-off-by: James Feist <james.feist@linux.intel.com>
-rw-r--r--hsbp-manager/src/hsbp_manager.cpp212
1 files changed, 133 insertions, 79 deletions
diff --git a/hsbp-manager/src/hsbp_manager.cpp b/hsbp-manager/src/hsbp_manager.cpp
index 83ebdf3..f25f266 100644
--- a/hsbp-manager/src/hsbp_manager.cpp
+++ b/hsbp-manager/src/hsbp_manager.cpp
@@ -18,7 +18,9 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/asio/steady_timer.hpp>
+#include <boost/container/flat_set.hpp>
#include <filesystem>
+#include <fstream>
#include <iostream>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
@@ -51,11 +53,20 @@ static std::string zeroPad(const uint8_t val)
struct Mux
{
- Mux(size_t busIn, size_t addressIn) : bus(busIn), address(addressIn)
+ Mux(size_t busIn, size_t addressIn, size_t channelsIn, size_t indexIn) :
+ bus(busIn), address(addressIn), channels(channelsIn), index(indexIn)
{
}
size_t bus;
size_t address;
+ size_t channels;
+ size_t index;
+
+ // to sort in the flat set
+ bool operator<(const Mux& rhs) const
+ {
+ return index < rhs.index;
+ }
};
enum class BlinkPattern : uint8_t
@@ -155,58 +166,41 @@ struct Drive
itemIface->get_object_path(), "xyz.openbmc_project.State.Drive");
rebuildingIface->register_property("Rebuilding", rebuilding);
rebuildingIface->initialize();
+ driveIface =
+ objServer.add_interface(itemIface->get_object_path(),
+ "xyz.openbmc_project.Inventory.Item.Drive");
+ driveIface->initialize();
}
virtual ~Drive()
{
objServer.remove_interface(itemIface);
objServer.remove_interface(operationalIface);
objServer.remove_interface(rebuildingIface);
- objServer.remove_interface(associationIface);
+ objServer.remove_interface(assetIface);
objServer.remove_interface(driveIface);
}
- void createAssociation(const std::string& path)
+ void createAsset(
+ const boost::container::flat_map<std::string, std::string>& data)
{
- if (associationIface != nullptr)
+ if (assetIface != nullptr)
{
return;
}
- associationIface = objServer.add_interface(
+ assetIface = objServer.add_interface(
itemIface->get_object_path(),
- "xyz.openbmc_project.Association.Definitions");
- std::vector<Association> associations;
- associations.emplace_back("inventory", "drive", path);
- associationIface->register_property("Associations", associations);
- associationIface->initialize();
- }
-
- void removeDriveIface()
- {
- objServer.remove_interface(driveIface);
- }
-
- void createDriveIface()
- {
- if (associationIface != nullptr || driveIface != nullptr)
+ "xyz.openbmc_project.Inventory.Decorator.Asset");
+ for (const auto& [key, value] : data)
{
- // this shouldn't be used if we found another provider of the drive
- // interface, or if we already created one
- return;
+ assetIface->register_property(key, value);
}
- driveIface =
- objServer.add_interface(itemIface->get_object_path(),
- "xyz.openbmc_project.Inventory.Item.Drive");
- driveIface->initialize();
- createAssociation(itemIface->get_object_path());
+ assetIface->initialize();
}
std::shared_ptr<sdbusplus::asio::dbus_interface> itemIface;
std::shared_ptr<sdbusplus::asio::dbus_interface> operationalIface;
std::shared_ptr<sdbusplus::asio::dbus_interface> rebuildingIface;
- std::shared_ptr<sdbusplus::asio::dbus_interface> associationIface;
-
- // if something else doesn't expose a driveInterface for this, we need to
- // export it ourselves
+ std::shared_ptr<sdbusplus::asio::dbus_interface> assetIface;
std::shared_ptr<sdbusplus::asio::dbus_interface> driveIface;
bool isNvme;
@@ -220,7 +214,7 @@ struct Backplane
bus(busIn),
address(addressIn), backplaneIndex(backplaneIndexIn - 1), name(nameIn),
timer(std::make_shared<boost::asio::steady_timer>(io)),
- muxes(std::make_shared<std::vector<Mux>>())
+ muxes(std::make_shared<boost::container::flat_set<Mux>>())
{
}
void run()
@@ -516,30 +510,28 @@ struct Backplane
std::vector<Drive> drives;
std::vector<std::shared_ptr<Led>> leds;
- std::shared_ptr<std::vector<Mux>> muxes;
+ std::shared_ptr<boost::container::flat_set<Mux>> muxes;
};
std::unordered_map<std::string, Backplane> backplanes;
+std::vector<Drive> ownerlessDrives; // drives without a backplane
-void createDriveInterfaces(size_t referenceCount)
+static size_t getDriveCount()
{
- if (referenceCount != 1)
- {
- return;
- }
- for (auto& [name, backplane] : backplanes)
+ size_t count = 0;
+ for (const auto& [key, backplane] : backplanes)
{
- for (Drive& drive : backplane.drives)
- {
- drive.createDriveIface();
- }
+ count += backplane.drives.size();
}
+ return count + ownerlessDrives.size();
}
-void updateAssociations()
+void updateAssets()
{
- constexpr const char* driveType =
- "xyz.openbmc_project.Inventory.Item.Drive";
+ static constexpr const char* nvmeType =
+ "xyz.openbmc_project.Inventory.Item.NVMe";
+ static const std::string assetTag =
+ "xyz.openbmc_project.Inventory.Decorator.Asset";
conn->async_method_call(
[](const boost::system::error_code ec, const GetSubTreeType& subtree) {
@@ -548,6 +540,10 @@ void updateAssociations()
std::cerr << "Error contacting mapper " << ec.message() << "\n";
return;
}
+
+ // drives may get an owner during this, or we might disover more
+ // drives
+ ownerlessDrives.clear();
for (const auto& [path, objDict] : subtree)
{
if (objDict.empty())
@@ -561,48 +557,49 @@ void updateAssociations()
{
continue;
}
- std::shared_ptr<bool> referenceCount = std::make_shared<bool>();
+ if (std::find(objDict.begin()->second.begin(),
+ objDict.begin()->second.end(),
+ assetTag) == objDict.begin()->second.end())
+ {
+ // no asset tag to associate to
+ continue;
+ }
+
conn->async_method_call(
- [path, referenceCount](
- const boost::system::error_code ec2,
- const boost::container::flat_map<
- std::string, std::variant<uint64_t>>& values) {
+ [path](const boost::system::error_code ec2,
+ const boost::container::flat_map<
+ std::string,
+ std::variant<uint64_t, std::string>>& values) {
if (ec2)
{
std::cerr << "Error Getting Config "
<< ec2.message() << " " << __FUNCTION__
<< "\n";
- createDriveInterfaces(referenceCount.use_count());
return;
}
auto findBus = values.find("Bus");
- auto findIndex = values.find("Index");
- if (findBus == values.end() ||
- findIndex == values.end())
+ if (findBus == values.end())
{
std::cerr << "Illegal interface at " << path
<< "\n";
- createDriveInterfaces(referenceCount.use_count());
return;
}
+ // find the mux bus and addr
size_t muxBus = static_cast<size_t>(
std::get<uint64_t>(findBus->second));
- size_t driveIndex = static_cast<size_t>(
- std::get<uint64_t>(findIndex->second));
std::filesystem::path muxPath =
"/sys/bus/i2c/devices/i2c-" +
std::to_string(muxBus) + "/mux_device";
if (!std::filesystem::is_symlink(muxPath))
{
std::cerr << path << " mux does not exist\n";
- createDriveInterfaces(referenceCount.use_count());
return;
}
- // we should be getting something of the form 7-0052 for
- // bus 7 addr 52
+ // we should be getting something of the form 7-0052
+ // for bus 7 addr 52
std::string fname =
std::filesystem::read_symlink(muxPath).filename();
auto findDash = fname.find('-');
@@ -611,7 +608,6 @@ void updateAssociations()
findDash + 1 >= fname.size())
{
std::cerr << path << " mux path invalid\n";
- createDriveInterfaces(referenceCount.use_count());
return;
}
@@ -621,9 +617,42 @@ void updateAssociations()
size_t bus = static_cast<size_t>(std::stoi(busStr));
size_t addr =
static_cast<size_t>(std::stoi(muxStr, nullptr, 16));
+ size_t muxIndex = 0;
+
+ // find the channel of the mux the drive is on
+ std::ifstream nameFile("/sys/bus/i2c/devices/i2c-" +
+ std::to_string(muxBus) +
+ "/name");
+ if (!nameFile)
+ {
+ std::cerr << "Unable to open name file of bus "
+ << muxBus << "\n";
+ return;
+ }
+
+ std::string nameStr;
+ std::getline(nameFile, nameStr);
+
+ // file is of the form "i2c-4-mux (chan_id 1)", get chan
+ // assume single digit chan
+ const std::string prefix = "chan_id ";
+ size_t findId = nameStr.find(prefix);
+ if (findId == std::string::npos ||
+ findId + 1 >= nameStr.size())
+ {
+ std::cerr << "Illegal name file on bus " << muxBus
+ << "\n";
+ }
+
+ std::string indexStr =
+ nameStr.substr(findId + prefix.size(), 1);
+
+ size_t driveIndex = std::stoi(indexStr);
+
Backplane* parent = nullptr;
for (auto& [name, backplane] : backplanes)
{
+ muxIndex = 0;
for (const Mux& mux : *(backplane.muxes))
{
if (bus == mux.bus && addr == mux.address)
@@ -631,37 +660,54 @@ void updateAssociations()
parent = &backplane;
break;
}
+ muxIndex += mux.channels;
}
}
+ boost::container::flat_map<std::string, std::string>
+ assetInventory;
+ const std::array<const char*, 4> assetKeys = {
+ "PartNumber", "SerialNumber", "Manufacturer",
+ "Model"};
+ for (const auto& [key, value] : values)
+ {
+ if (std::find(assetKeys.begin(), assetKeys.end(),
+ key) == assetKeys.end())
+ {
+ continue;
+ }
+ assetInventory[key] = std::get<std::string>(value);
+ }
+
+ // assume its a M.2 or something without a hsbp
if (parent == nullptr)
{
- std::cerr << "Failed to find mux at bus " << bus
- << ", addr " << addr << "\n";
- createDriveInterfaces(referenceCount.use_count());
+ auto& drive = ownerlessDrives.emplace_back(
+ getDriveCount() + 1, true, true, true, false);
+ drive.createAsset(assetInventory);
return;
}
+
+ driveIndex += muxIndex;
+
if (parent->drives.size() <= driveIndex)
{
-
std::cerr << "Illegal drive index at " << path
<< " " << driveIndex << "\n";
- createDriveInterfaces(referenceCount.use_count());
return;
}
+
Drive& drive = parent->drives[driveIndex];
- drive.removeDriveIface();
- drive.createAssociation(path);
- createDriveInterfaces(referenceCount.use_count());
+ drive.createAsset(assetInventory);
},
owner, path, "org.freedesktop.DBus.Properties", "GetAll",
- "xyz.openbmc_project.Inventory.Item.Drive");
+ "" /*all interface items*/);
}
},
mapper::busName, mapper::path, mapper::interface, mapper::subtree, "/",
- 0, std::array<const char*, 1>{driveType});
+ 0, std::array<const char*, 1>{nvmeType});
}
-void populateMuxes(std::shared_ptr<std::vector<Mux>> muxes,
+void populateMuxes(std::shared_ptr<boost::container::flat_set<Mux>> muxes,
std::string& rootPath)
{
const static std::array<const std::string, 4> muxTypes = {
@@ -679,7 +725,8 @@ void populateMuxes(std::shared_ptr<std::vector<Mux>> muxes,
}
std::shared_ptr<std::function<void()>> callback =
std::make_shared<std::function<void()>>(
- []() { updateAssociations(); });
+ []() { updateAssets(); });
+ size_t index = 0; // as we use a flat map, these are sorted
for (const auto& [path, objDict] : subtree)
{
if (objDict.empty() || objDict.begin()->second.empty())
@@ -708,10 +755,12 @@ void populateMuxes(std::shared_ptr<std::vector<Mux>> muxes,
}
conn->async_method_call(
- [path, muxes, callback](
+ [path, muxes, callback, index](
const boost::system::error_code ec2,
const boost::container::flat_map<
- std::string, std::variant<uint64_t>>& values) {
+ std::string,
+ std::variant<uint64_t, std::vector<std::string>>>&
+ values) {
if (ec2)
{
std::cerr << "Error Getting Config "
@@ -721,6 +770,7 @@ void populateMuxes(std::shared_ptr<std::vector<Mux>> muxes,
}
auto findBus = values.find("Bus");
auto findAddress = values.find("Address");
+ auto findChannelNames = values.find("ChannelNames");
if (findBus == values.end() ||
findAddress == values.end())
{
@@ -732,7 +782,10 @@ void populateMuxes(std::shared_ptr<std::vector<Mux>> muxes,
std::get<uint64_t>(findBus->second));
size_t address = static_cast<size_t>(
std::get<uint64_t>(findAddress->second));
- muxes->emplace_back(bus, address);
+ std::vector<std::string> channels =
+ std::get<std::vector<std::string>>(
+ findChannelNames->second);
+ muxes->emplace(bus, address, channels.size(), index);
if (callback.use_count() == 1)
{
(*callback)();
@@ -740,6 +793,7 @@ void populateMuxes(std::shared_ptr<std::vector<Mux>> muxes,
},
owner, path, "org.freedesktop.DBus.Properties", "GetAll",
*interface);
+ index++;
}
},
mapper::busName, mapper::path, mapper::interface, mapper::subtree,
@@ -849,7 +903,7 @@ int main()
sdbusplus::bus::match::match drive(
*conn,
"type='signal',member='PropertiesChanged',arg0='xyz.openbmc_project."
- "Inventory.Item.Drive'",
+ "Inventory.Item.NVMe'",
[&callbackTimer](sdbusplus::message::message& message) {
callbackTimer.expires_after(std::chrono::seconds(2));
if (message.get_sender() == conn->get_unique_name())