regulators: Only configure/monitor if present
Enhance the configure and monitor operations to only be performed if the
device is present.
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: I57fed4f92937b808ac6f8c37899e28d6009747e6
diff --git a/phosphor-regulators/src/device.cpp b/phosphor-regulators/src/device.cpp
index 1290077..8ae7afb 100644
--- a/phosphor-regulators/src/device.cpp
+++ b/phosphor-regulators/src/device.cpp
@@ -69,27 +69,34 @@
void Device::configure(Services& services, System& system, Chassis& chassis)
{
- // If configuration changes are defined for this device, apply them
- if (configuration)
+ // Verify device is present
+ if (isPresent(services, system, chassis))
{
- configuration->execute(services, system, chassis, *this);
- }
+ // If configuration changes are defined for this device, apply them
+ if (configuration)
+ {
+ configuration->execute(services, system, chassis, *this);
+ }
- // Configure rails
- for (std::unique_ptr<Rail>& rail : rails)
- {
- rail->configure(services, system, chassis, *this);
+ // Configure rails
+ for (std::unique_ptr<Rail>& rail : rails)
+ {
+ rail->configure(services, system, chassis, *this);
+ }
}
}
void Device::monitorSensors(Services& services, System& system,
Chassis& chassis)
{
-
- // Monitor sensors in each rail
- for (std::unique_ptr<Rail>& rail : rails)
+ // Verify device is present
+ if (isPresent(services, system, chassis))
{
- rail->monitorSensors(services, system, chassis, *this);
+ // Monitor sensors in each rail
+ for (std::unique_ptr<Rail>& rail : rails)
+ {
+ rail->monitorSensors(services, system, chassis, *this);
+ }
}
}
diff --git a/phosphor-regulators/src/device.hpp b/phosphor-regulators/src/device.hpp
index 75ff904..8ef37fb 100644
--- a/phosphor-regulators/src/device.hpp
+++ b/phosphor-regulators/src/device.hpp
@@ -184,6 +184,25 @@
}
/**
+ * Returns whether this device is present.
+ *
+ * @return true if device is present, false otherwise
+ */
+ bool isPresent(Services& services, System& system, Chassis& chassis)
+ {
+ if (presenceDetection)
+ {
+ // Execute presence detection to determine if device is present
+ return presenceDetection->execute(services, system, chassis, *this);
+ }
+ else
+ {
+ // No presence detection defined; assume device is present
+ return true;
+ }
+ }
+
+ /**
* Returns whether this device is a voltage regulator.
*
* @return true if device is a voltage regulator, false otherwise
diff --git a/phosphor-regulators/test/device_tests.cpp b/phosphor-regulators/test/device_tests.cpp
index 717bb9d..594578f 100644
--- a/phosphor-regulators/test/device_tests.cpp
+++ b/phosphor-regulators/test/device_tests.cpp
@@ -295,6 +295,57 @@
TEST(DeviceTests, Configure)
{
+ // Test where device is not present
+ {
+ // Create mock services. No logging should occur.
+ MockServices services{};
+ MockJournal& journal = services.getMockJournal();
+ EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
+ EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
+
+ // Create PresenceDetection. Indicates device is not present.
+ std::unique_ptr<MockAction> presAction = std::make_unique<MockAction>();
+ EXPECT_CALL(*presAction, execute).Times(1).WillOnce(Return(false));
+ std::vector<std::unique_ptr<Action>> presActions{};
+ presActions.emplace_back(std::move(presAction));
+ std::unique_ptr<PresenceDetection> presenceDetection =
+ std::make_unique<PresenceDetection>(std::move(presActions));
+
+ // Create Configuration. Action inside it should not be executed.
+ std::optional<double> volts{};
+ std::unique_ptr<MockAction> confAction = std::make_unique<MockAction>();
+ EXPECT_CALL(*confAction, execute).Times(0);
+ std::vector<std::unique_ptr<Action>> confActions{};
+ confActions.emplace_back(std::move(confAction));
+ std::unique_ptr<Configuration> configuration =
+ std::make_unique<Configuration>(volts, std::move(confActions));
+
+ // Create Device
+ std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
+ std::unique_ptr<Device> device = std::make_unique<Device>(
+ "reg1", true,
+ "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
+ std::move(i2cInterface), std::move(presenceDetection),
+ std::move(configuration));
+ Device* devicePtr = device.get();
+
+ // Create Chassis that contains Device
+ std::vector<std::unique_ptr<Device>> devices{};
+ devices.emplace_back(std::move(device));
+ std::unique_ptr<Chassis> chassis =
+ std::make_unique<Chassis>(1, std::move(devices));
+ Chassis* chassisPtr = chassis.get();
+
+ // Create System that contains Chassis
+ std::vector<std::unique_ptr<Rule>> rules{};
+ std::vector<std::unique_ptr<Chassis>> chassisVec{};
+ chassisVec.emplace_back(std::move(chassis));
+ System system{std::move(rules), std::move(chassisVec)};
+
+ // Call configure(). Should do nothing.
+ devicePtr->configure(services, system, *chassisPtr);
+ }
+
// Test where Configuration and Rails were not specified in constructor
{
// Create mock services. No logging should occur.
@@ -548,6 +599,115 @@
}
}
+TEST(DeviceTests, IsPresent)
+{
+ // Test where PresenceDetection not specified in constructor
+ {
+ // Create Device
+ std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
+ std::unique_ptr<Device> device = std::make_unique<Device>(
+ "reg1", true,
+ "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
+ std::move(i2cInterface));
+ Device* devicePtr = device.get();
+
+ // Create Chassis that contains Device
+ std::vector<std::unique_ptr<Device>> devices{};
+ devices.emplace_back(std::move(device));
+ std::unique_ptr<Chassis> chassis =
+ std::make_unique<Chassis>(1, std::move(devices));
+ Chassis* chassisPtr = chassis.get();
+
+ // Create System that contains Chassis
+ std::vector<std::unique_ptr<Rule>> rules{};
+ std::vector<std::unique_ptr<Chassis>> chassisVec{};
+ chassisVec.emplace_back(std::move(chassis));
+ System system{std::move(rules), std::move(chassisVec)};
+
+ // Create MockServices
+ MockServices services{};
+
+ // Since no PresenceDetection defined, isPresent() should return true
+ EXPECT_TRUE(devicePtr->isPresent(services, system, *chassisPtr));
+ }
+
+ // Test where PresenceDetection was specified in constructor: Is present
+ {
+ // Create PresenceDetection. Indicates device is present.
+ std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
+ EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
+ std::vector<std::unique_ptr<Action>> actions{};
+ actions.emplace_back(std::move(action));
+ std::unique_ptr<PresenceDetection> presenceDetection =
+ std::make_unique<PresenceDetection>(std::move(actions));
+
+ // Create Device
+ std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
+ std::unique_ptr<Device> device = std::make_unique<Device>(
+ "reg1", true,
+ "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
+ std::move(i2cInterface), std::move(presenceDetection));
+ Device* devicePtr = device.get();
+
+ // Create Chassis that contains Device
+ std::vector<std::unique_ptr<Device>> devices{};
+ devices.emplace_back(std::move(device));
+ std::unique_ptr<Chassis> chassis =
+ std::make_unique<Chassis>(1, std::move(devices));
+ Chassis* chassisPtr = chassis.get();
+
+ // Create System that contains Chassis
+ std::vector<std::unique_ptr<Rule>> rules{};
+ std::vector<std::unique_ptr<Chassis>> chassisVec{};
+ chassisVec.emplace_back(std::move(chassis));
+ System system{std::move(rules), std::move(chassisVec)};
+
+ // Create MockServices
+ MockServices services{};
+
+ // PresenceDetection::execute() and isPresent() should return true
+ EXPECT_TRUE(devicePtr->isPresent(services, system, *chassisPtr));
+ }
+
+ // Test where PresenceDetection was specified in constructor: Is not present
+ {
+ // Create PresenceDetection. Indicates device is not present.
+ std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
+ EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
+ std::vector<std::unique_ptr<Action>> actions{};
+ actions.emplace_back(std::move(action));
+ std::unique_ptr<PresenceDetection> presenceDetection =
+ std::make_unique<PresenceDetection>(std::move(actions));
+
+ // Create Device
+ std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
+ std::unique_ptr<Device> device = std::make_unique<Device>(
+ "reg1", true,
+ "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
+ std::move(i2cInterface), std::move(presenceDetection));
+ Device* devicePtr = device.get();
+
+ // Create Chassis that contains Device
+ std::vector<std::unique_ptr<Device>> devices{};
+ devices.emplace_back(std::move(device));
+ std::unique_ptr<Chassis> chassis =
+ std::make_unique<Chassis>(1, std::move(devices));
+ Chassis* chassisPtr = chassis.get();
+
+ // Create System that contains Chassis
+ std::vector<std::unique_ptr<Rule>> rules{};
+ std::vector<std::unique_ptr<Chassis>> chassisVec{};
+ chassisVec.emplace_back(std::move(chassis));
+ System system{std::move(rules), std::move(chassisVec)};
+
+ // Create MockServices
+ MockServices services{};
+
+ // PresenceDetection::execute() and isPresent() should return false
+ EXPECT_FALSE(devicePtr->isPresent(services, system, *chassisPtr));
+ }
+}
+
TEST(DeviceTests, IsRegulator)
{
Device device{
@@ -559,6 +719,9 @@
TEST(DeviceTests, MonitorSensors)
{
+ // Test where device is not present
+ // TODO: Add this test when sensoring monitoring is fully implemented
+
// Test where Rails were not specified in constructor
{
// Create mock services. No logging should occur.