1 #include <powercap.hpp> 2 #include <phosphor-logging/log.hpp> 3 4 namespace open_power 5 { 6 namespace occ 7 { 8 namespace powercap 9 { 10 11 constexpr auto PCAP_PATH = "/xyz/openbmc_project/control/host0/power_cap"; 12 constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap"; 13 14 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; 15 constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; 16 constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; 17 18 constexpr auto POWER_CAP_PROP = "PowerCap"; 19 constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable"; 20 21 using namespace phosphor::logging; 22 23 std::string PowerCap::getService(std::string path, 24 std::string interface) 25 { 26 auto mapper = bus.new_method_call(MAPPER_BUSNAME, 27 MAPPER_PATH, 28 MAPPER_INTERFACE, 29 "GetObject"); 30 31 mapper.append(path, std::vector<std::string>({interface})); 32 auto mapperResponseMsg = bus.call(mapper); 33 34 if (mapperResponseMsg.is_method_error()) 35 { 36 log<level::ERR>("Error in mapper call", 37 entry("PATH=%s", path.c_str()), 38 entry("INTERFACE=%s", interface.c_str())); 39 // TODO openbmc/openbmc#851 - Once available, throw returned error 40 throw std::runtime_error("Error in mapper call"); 41 } 42 43 std::map<std::string, std::vector<std::string>> mapperResponse; 44 mapperResponseMsg.read(mapperResponse); 45 if (mapperResponse.empty()) 46 { 47 log<level::ERR>("Error reading mapper response", 48 entry("PATH=%s", path.c_str()), 49 entry("INTERFACE=%s", interface.c_str())); 50 // TODO openbmc/openbmc#1712 - Handle empty mapper resp. consistently 51 throw std::runtime_error("Error reading mapper response"); 52 } 53 54 return mapperResponse.begin()->first; 55 } 56 57 uint32_t PowerCap::getOccInput(uint32_t pcap, bool pcapEnabled) 58 { 59 if (!pcapEnabled) 60 { 61 // Pcap disabled, return 0 to indicate disabled 62 return 0; 63 } 64 65 // If pcap is not disabled then just return the pcap with the derating 66 // factor applied. 67 return( (static_cast<uint64_t>(pcap) * PS_DERATING_FACTOR) /100); 68 } 69 70 uint32_t PowerCap::getPcap() 71 { 72 auto settingService = getService(PCAP_PATH,PCAP_INTERFACE); 73 74 auto method = this->bus.new_method_call(settingService.c_str(), 75 PCAP_PATH, 76 "org.freedesktop.DBus.Properties", 77 "Get"); 78 79 method.append(PCAP_INTERFACE, POWER_CAP_PROP); 80 auto reply = this->bus.call(method); 81 82 if (reply.is_method_error()) 83 { 84 log<level::ERR>("Error in getPcap prop"); 85 return 0; 86 } 87 sdbusplus::message::variant<uint32_t> pcap; 88 reply.read(pcap); 89 90 return pcap.get<uint32_t>(); 91 } 92 93 bool PowerCap::getPcapEnabled() 94 { 95 auto settingService = getService(PCAP_PATH,PCAP_INTERFACE); 96 97 auto method = this->bus.new_method_call(settingService.c_str(), 98 PCAP_PATH, 99 "org.freedesktop.DBus.Properties", 100 "Get"); 101 102 method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP); 103 auto reply = this->bus.call(method); 104 105 if (reply.is_method_error()) 106 { 107 log<level::ERR>("Error in getPcapEnabled prop"); 108 return 0; 109 } 110 sdbusplus::message::variant<bool> pcapEnabled; 111 reply.read(pcapEnabled); 112 113 return pcapEnabled.get<bool>(); 114 } 115 116 void PowerCap::pcapChanged(sdbusplus::message::message& msg) 117 { 118 if (!occStatus.occActive()) 119 { 120 // Nothing to do 121 return; 122 } 123 124 uint32_t pcap = 0; 125 bool pcapEnabled = false; 126 127 std::string msgSensor; 128 std::map<std::string, sdbusplus::message::variant<uint32_t, bool>> msgData; 129 msg.read(msgSensor, msgData); 130 131 // Retrieve which property changed via the msg and read the other one 132 auto valPropMap = msgData.find(POWER_CAP_PROP); 133 if (valPropMap != msgData.end()) 134 { 135 pcap = sdbusplus::message::variant_ns::get<uint32_t>( 136 valPropMap->second); 137 pcapEnabled = getPcapEnabled(); 138 } 139 else 140 { 141 valPropMap = msgData.find(POWER_CAP_ENABLE_PROP); 142 if (valPropMap != msgData.end()) 143 { 144 pcapEnabled = sdbusplus::message::variant_ns::get<bool>( 145 valPropMap->second); 146 pcap = getPcap(); 147 } 148 else 149 { 150 log<level::INFO>("Unknown power cap property changed"); 151 return; 152 } 153 } 154 155 log<level::INFO>("Power Cap Property Change", 156 entry("PCAP=%u",pcap), 157 entry("PCAP_ENABLED=%u",pcapEnabled)); 158 159 // Determine desired action to write to occ 160 auto occInput = getOccInput(pcap, pcapEnabled); 161 log<level::DEBUG>("Writing new power cap setting to OCC", 162 entry("OCC_PCAP_VAL=%u",occInput)); 163 164 // Write action to occ 165 // TODO 166 167 return; 168 } 169 170 } // namespace open_power 171 172 } // namespace occ 173 174 }// namespace powercap 175