Prep CPU sensor for no-overlays
Get data from comparing bus and address from sysfs
Change-Id: Ibef93f6921ab26602ff970b0ee1e32a64d5c5717
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
diff --git a/sensors/include/CPUSensor.hpp b/sensors/include/CPUSensor.hpp
index 8f7d2f0..4229801 100644
--- a/sensors/include/CPUSensor.hpp
+++ b/sensors/include/CPUSensor.hpp
@@ -6,12 +6,24 @@
class CPUSensor : public Sensor
{
+ public:
+ std::string name;
+ std::string configuration;
+ CPUSensor(const std::string &path, const std::string &objectType,
+ sdbusplus::asio::object_server &object_server,
+ std::shared_ptr<sdbusplus::asio::connection> &conn,
+ boost::asio::io_service &io, const std::string &fan_name,
+ std::vector<thresholds::Threshold> &&thresholds,
+ const std::string &configuration);
+ ~CPUSensor();
+ constexpr static unsigned int SENSOR_SCALE_FACTOR = 1000;
+ constexpr static unsigned int SENSOR_POLL_MS = 1000;
+
private:
std::string path;
std::string objectType;
sdbusplus::asio::object_server &objServer;
std::shared_ptr<sdbusplus::asio::connection> dbusConnection;
- std::string name;
boost::asio::posix::stream_descriptor input_dev;
boost::asio::deadline_timer wait_timer;
boost::asio::streambuf read_buf;
@@ -25,16 +37,4 @@
void set_initial_properties(
std::shared_ptr<sdbusplus::asio::connection> &conn);
-
- public:
- std::string configuration;
- CPUSensor(const std::string &path, const std::string &objectType,
- sdbusplus::asio::object_server &object_server,
- std::shared_ptr<sdbusplus::asio::connection> &conn,
- boost::asio::io_service &io, const std::string &fan_name,
- std::vector<thresholds::Threshold> &&thresholds,
- const std::string &configuration);
- ~CPUSensor();
- constexpr static unsigned int SENSOR_SCALE_FACTOR = 1000;
- constexpr static unsigned int SENSOR_POLL_MS = 1000;
};
diff --git a/sensors/src/CPUSensorMain.cpp b/sensors/src/CPUSensorMain.cpp
index cc9fb91..fb0ede4 100644
--- a/sensors/src/CPUSensorMain.cpp
+++ b/sensors/src/CPUSensorMain.cpp
@@ -42,24 +42,23 @@
struct CPUConfig
{
- CPUConfig(const int& address, const std::string& overlayName,
- const State& st) :
- addr(address),
- ovName(overlayName), state(st)
+ CPUConfig(const uint64_t& bus, const uint64_t& addr,
+ const std::string& name, const State& state) :
+ bus(bus),
+ addr(addr), name(name), state(state)
{
}
+ int bus;
int addr;
- std::string ovName;
+ std::string name;
State state;
bool operator<(const CPUConfig& rhs) const
{
- return (ovName < rhs.ovName);
+ return (name < rhs.name);
}
};
-static constexpr const char* DT_OVERLAY = "/usr/bin/dtoverlay";
-static constexpr const char* OVERLAY_DIR = "/tmp/overlays";
static constexpr const char* PECI_DEV = "/dev/peci-0";
static constexpr const unsigned int RANK_NUM_MAX = 8;
@@ -107,86 +106,140 @@
useCache = true;
}
- std::vector<fs::path> oemNamePaths;
+ std::vector<fs::path> hwmonNamePaths;
if (!find_files(fs::path(R"(/sys/bus/peci/devices)"),
- R"(peci-\d+/\d+-.+/of_node/oemname1$)", oemNamePaths, 2))
+ R"(peci-\d+/\d+-.+/peci-.+/hwmon/hwmon\d+/name$)",
+ hwmonNamePaths, 1))
{
std::cerr << "No CPU sensors in system\n";
return true;
}
- for (fs::path& oemNamePath : oemNamePaths)
+ boost::container::flat_set<std::string> scannedDirectories;
+ boost::container::flat_set<std::string> createdSensors;
+
+ for (fs::path& hwmonNamePath : hwmonNamePaths)
{
- std::ifstream nameFile(oemNamePath);
- if (!nameFile.good())
+ const std::string& pathStr = hwmonNamePath.string();
+ auto hwmonDirectory = hwmonNamePath.parent_path();
+
+ auto ret = scannedDirectories.insert(hwmonDirectory.string());
+ if (!ret.second)
{
- std::cerr << "Failure reading " << oemNamePath << "\n";
+ continue; // already searched this path
+ }
+
+ fs::path::iterator it = hwmonNamePath.begin();
+ std::advance(it, 6); // pick the 6th part for a PECI client device name
+ std::string deviceName = *it;
+ auto findHyphen = deviceName.find("-");
+ if (findHyphen == std::string::npos)
+ {
+ std::cerr << "found bad device " << deviceName << "\n";
continue;
}
- std::string oemName;
- std::getline(nameFile, oemName);
+ std::string busStr = deviceName.substr(0, findHyphen);
+ std::string addrStr = deviceName.substr(findHyphen + 1);
+
+ size_t bus = 0;
+ size_t addr = 0;
+ try
+ {
+ bus = std::stoi(busStr);
+ addr = std::stoi(addrStr, 0, 16);
+ }
+ catch (std::invalid_argument)
+ {
+ continue;
+ }
+
+ std::ifstream nameFile(hwmonNamePath);
+ if (!nameFile.good())
+ {
+ std::cerr << "Failure reading " << hwmonNamePath << "\n";
+ continue;
+ }
+ std::string hwmonName;
+ std::getline(nameFile, hwmonName);
nameFile.close();
- if (!oemName.size())
+ if (!hwmonName.size())
{
// shouldn't have an empty name file
continue;
}
- oemName.pop_back(); // remove trailing null
if (DEBUG)
- std::cout << "Checking: " << oemNamePath << ": " << oemName << "\n";
+ {
+ std::cout << "Checking: " << hwmonNamePath << ": " << hwmonName
+ << "\n";
+ }
+ std::string sensorType;
const SensorData* sensorData = nullptr;
const std::string* interfacePath = nullptr;
- for (const std::pair<sdbusplus::message::object_path, SensorData>&
- sensor : sensorConfigurations)
- {
- if (!boost::ends_with(sensor.first.str, oemName))
- {
- continue;
- }
- sensorData = &(sensor.second);
- interfacePath = &(sensor.first.str);
- break;
- }
- if (sensorData == nullptr)
- {
- std::cerr << "failed to find match for " << oemName << "\n";
- continue;
- }
const std::pair<std::string, boost::container::flat_map<
std::string, BasicVariantType>>*
baseConfiguration = nullptr;
- std::string sensorObjectType;
- for (const char* type : SENSOR_TYPES)
- {
- sensorObjectType = CONFIG_PREFIX + std::string(type);
- auto sensorBase = sensorData->find(sensorObjectType);
- if (sensorBase != sensorData->end())
- {
- baseConfiguration = &(*sensorBase);
- break;
- }
- }
- if (baseConfiguration == nullptr)
+ for (const std::pair<sdbusplus::message::object_path, SensorData>&
+ sensor : sensorConfigurations)
{
- std::cerr << "error finding base configuration for" << oemName
- << "\n";
+ sensorData = &(sensor.second);
+ for (const char* type : SENSOR_TYPES)
+ {
+ sensorType = CONFIG_PREFIX + std::string(type);
+ auto sensorBase = sensorData->find(sensorType);
+ if (sensorBase != sensorData->end())
+ {
+ baseConfiguration = &(*sensorBase);
+ break;
+ }
+ }
+ if (baseConfiguration == nullptr)
+ {
+ std::cerr << "error finding base configuration for" << hwmonName
+ << "\n";
+ continue;
+ }
+ auto configurationBus = baseConfiguration->second.find("Bus");
+ auto configurationAddress =
+ baseConfiguration->second.find("Address");
+
+ if (configurationBus == baseConfiguration->second.end() ||
+ configurationAddress == baseConfiguration->second.end())
+ {
+ std::cerr << "error finding bus or address in configuration";
+ continue;
+ }
+
+ if (sdbusplus::message::variant_ns::get<uint64_t>(
+ configurationBus->second) != bus ||
+ sdbusplus::message::variant_ns::get<uint64_t>(
+ configurationAddress->second) != addr)
+ {
+ continue;
+ }
+
+ interfacePath = &(sensor.first.str);
+ break;
+ }
+ if (interfacePath == nullptr)
+ {
+ std::cerr << "failed to find match for " << hwmonName << "\n";
continue;
}
auto findCpuId = baseConfiguration->second.find("CpuID");
if (findCpuId == baseConfiguration->second.end())
{
- std::cerr << "could not determine CPU ID for " << oemName << "\n";
+ std::cerr << "could not determine CPU ID for " << hwmonName << "\n";
continue;
}
- int cpuId = variant_ns::visit(VariantToIntVisitor(), findCpuId->second);
+ int cpuId =
+ variant_ns::visit(VariantToUnsignedIntVisitor(), findCpuId->second);
- auto directory = oemNamePath.parent_path().parent_path();
+ auto directory = hwmonNamePath.parent_path();
std::vector<fs::path> inputPaths;
- if (!find_files(fs::path(directory),
- R"(peci-.+/hwmon/hwmon\d+/temp\d+_input$)", inputPaths,
+ if (!find_files(fs::path(directory), R"(temp\d+_input$)", inputPaths,
0))
{
std::cerr << "No temperature sensors in system\n";
@@ -209,6 +262,18 @@
std::getline(labelFile, label);
labelFile.close();
std::string sensorName = label + " CPU" + std::to_string(cpuId);
+
+ auto findSensor = sensors.find(sensorName);
+ if (findSensor != sensors.end())
+ {
+ if (DEBUG)
+ {
+ std::cout << "Skipped: " << inputPath << ": " << sensorName
+ << " is already created\n";
+ }
+ continue;
+ }
+
std::vector<thresholds::Threshold> sensorThresholds;
std::string labelHead = label.substr(0, label.find(" "));
ParseThresholdsFromConfig(*sensorData, sensorThresholds,
@@ -223,42 +288,69 @@
}
}
sensors[sensorName] = std::make_unique<CPUSensor>(
- inputPathStr, sensorObjectType, objectServer, dbusConnection,
- io, sensorName, std::move(sensorThresholds), *interfacePath);
+ inputPathStr, sensorType, objectServer, dbusConnection, io,
+ sensorName, std::move(sensorThresholds), *interfacePath);
+ createdSensors.insert(sensorName);
if (DEBUG)
+ {
std::cout << "Mapped: " << inputPath << " to " << sensorName
<< "\n";
+ }
}
}
- std::cout << "Sensor creation completed\n";
+ if (createdSensors.size())
+ {
+ std::cout << "Sensor" << (createdSensors.size() == 1 ? " is" : "s are")
+ << " created\n";
+ }
return true;
}
-void reloadOverlay(const std::string& overlay)
+void exportDevice(const CPUConfig& config)
{
- boost::process::child c1(DT_OVERLAY, "-d", OVERLAY_DIR, "-r", overlay);
- c1.wait();
- if (c1.exit_code())
+ std::ostringstream hex;
+ hex << std::hex << config.addr;
+ const std::string& addrHexStr = hex.str();
+ std::string busStr = std::to_string(config.bus);
+
+ std::string parameters = "peci-client 0x" + addrHexStr;
+ std::string device = "/sys/bus/peci/devices/peci-" + busStr + "/new_device";
+
+ std::experimental::filesystem::path devicePath(device);
+ const std::string& dir = devicePath.parent_path().string();
+ for (const auto& path :
+ std::experimental::filesystem::directory_iterator(dir))
{
- if (DEBUG)
+ if (!std::experimental::filesystem::is_directory(path))
{
- std::cout << "DTOverlay unload error with file " << overlay
- << ". error: " << c1.exit_code() << "\n";
+ continue;
}
- /* fall through anyway */
+ const std::string& directoryName = path.path().filename();
+ if (boost::starts_with(directoryName, busStr) &&
+ boost::ends_with(directoryName, addrHexStr))
+ {
+ if (DEBUG)
+ {
+ std::cout << parameters << " on bus " << busStr
+ << " is already exported\n";
+ }
+ return;
+ }
}
- boost::process::child c2(DT_OVERLAY, "-d", OVERLAY_DIR, overlay);
- c2.wait();
- if (c2.exit_code())
+ std::ofstream deviceFile(device);
+ if (!deviceFile.good())
{
- std::cerr << "DTOverlay load error with file " << overlay
- << ". error: " << c2.exit_code() << "\n";
+ std::cerr << "Error writing " << device << "\n";
return;
}
+ deviceFile << parameters;
+ deviceFile.close();
+
+ std::cout << parameters << " on bus " << busStr << " is exported\n";
}
void detectCpu(boost::asio::deadline_timer& timer, boost::asio::io_service& io,
@@ -325,12 +417,12 @@
{
if (config.state == State::OFF)
{
- std::cout << config.ovName << " is detected\n";
- reloadOverlay(config.ovName);
+ std::cout << config.name << " is detected\n";
+ exportDevice(config);
}
if (state == State::READY)
{
- std::cout << "DIMM(s) on " << config.ovName
+ std::cout << "DIMM(s) on " << config.name
<< " is/are detected\n";
}
config.state = state;
@@ -354,7 +446,9 @@
}
if (DEBUG)
- std::cout << config.ovName << ", state: " << config.state << "\n";
+ {
+ std::cout << config.name << ", state: " << config.state << "\n";
+ }
}
close(file);
@@ -388,7 +482,7 @@
}
}
-void getCpuConfig(const std::shared_ptr<sdbusplus::asio::connection>& systemBus,
+bool getCpuConfig(const std::shared_ptr<sdbusplus::asio::connection>& systemBus,
boost::container::flat_set<CPUConfig>& configs)
{
ManagedObjectType sensorConfigurations;
@@ -399,7 +493,7 @@
if (!getSensorConfiguration(CONFIG_PREFIX + std::string(type),
systemBus, sensorConfigurations, useCache))
{
- return;
+ return false;
}
useCache = true;
}
@@ -421,14 +515,6 @@
continue;
}
- auto findAddress = config.second.find("Address");
- if (findAddress == config.second.end())
- {
- continue;
- }
- int addr = variant_ns::visit(VariantToIntVisitor(),
- findAddress->second);
-
auto findName = config.second.find("Name");
if (findName == config.second.end())
{
@@ -438,22 +524,47 @@
VariantToStringVisitor(), findName->second);
std::string name =
std::regex_replace(nameRaw, ILLEGAL_NAME_REGEX, "_");
- std::string overlayName = name + "_" + type;
+
+ auto findBus = config.second.find("Bus");
+ if (findBus == config.second.end())
+ {
+ std::cerr << "Can't find 'Bus' setting in " << name << "\n";
+ continue;
+ }
+ uint64_t bus = variant_ns::visit(VariantToUnsignedIntVisitor(),
+ findBus->second);
+
+ auto findAddress = config.second.find("Address");
+ if (findAddress == config.second.end())
+ {
+ std::cerr << "Can't find 'Address' setting in " << name
+ << "\n";
+ continue;
+ }
+ uint64_t addr = variant_ns::visit(VariantToUnsignedIntVisitor(),
+ findAddress->second);
if (DEBUG)
{
+ std::cout << "bus: " << bus << "\n";
std::cout << "addr: " << addr << "\n";
std::cout << "name: " << name << "\n";
std::cout << "type: " << type << "\n";
- std::cout << "overlayName: " << overlayName << "\n";
}
- configs.emplace(addr, overlayName, State::OFF);
+ configs.emplace(bus, addr, name, State::OFF);
}
}
}
- std::cout << "CPU configs parsed\n";
+ if (configs.size())
+ {
+ std::cout << "CPU config" << (configs.size() == 1 ? " is" : "s are")
+ << " parsed\n";
+ return true;
+ }
+
+ return false;
}
int main(int argc, char** argv)
@@ -467,13 +578,27 @@
boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>> sensors;
std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
boost::asio::deadline_timer pingTimer(io);
- getCpuConfig(systemBus, configs);
- if (configs.size())
- {
- detectCpu(pingTimer, io, objectServer, sensors, configs, systemBus);
- }
-
boost::asio::deadline_timer filterTimer(io);
+
+ filterTimer.expires_from_now(boost::posix_time::seconds(1));
+ filterTimer.async_wait([&](const boost::system::error_code& ec) {
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ /* we were canceled*/
+ return;
+ }
+ else if (ec)
+ {
+ std::cerr << "timer error\n";
+ return;
+ }
+
+ if (getCpuConfig(systemBus, configs))
+ {
+ detectCpu(pingTimer, io, objectServer, sensors, configs, systemBus);
+ }
+ });
+
std::function<void(sdbusplus::message::message&)> eventHandler =
[&](sdbusplus::message::message& message) {
if (message.is_method_error())
@@ -481,9 +606,14 @@
std::cerr << "callback method error\n";
return;
}
+
+ if (DEBUG)
+ {
+ std::cout << message.get_path() << " is changed\n";
+ }
+
// this implicitly cancels the timer
filterTimer.expires_from_now(boost::posix_time::seconds(1));
-
filterTimer.async_wait([&](const boost::system::error_code& ec) {
if (ec == boost::asio::error::operation_aborted)
{
@@ -496,9 +626,7 @@
return;
}
- getCpuConfig(systemBus, configs);
-
- if (configs.size())
+ if (getCpuConfig(systemBus, configs))
{
detectCpu(pingTimer, io, objectServer, sensors, configs,
systemBus);