1 /** 2 * Copyright 2017 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "pid/builder.hpp" 18 19 #include "conf.hpp" 20 #include "pid/controller.hpp" 21 #include "pid/fancontroller.hpp" 22 #include "pid/stepwisecontroller.hpp" 23 #include "pid/thermalcontroller.hpp" 24 25 #include <sdbusplus/bus.hpp> 26 27 #include <iostream> 28 #include <memory> 29 #include <unordered_map> 30 31 namespace pid_control 32 { 33 34 static constexpr bool deferSignals = true; 35 static constexpr auto objectPath = "/xyz/openbmc_project/settings/fanctrl/zone"; 36 37 static std::string getControlPath(int64_t zone) 38 { 39 return std::string(objectPath) + std::to_string(zone); 40 } 41 42 std::unordered_map<int64_t, std::unique_ptr<PIDZone>> 43 buildZones(const std::map<int64_t, conf::PIDConf>& zonePids, 44 std::map<int64_t, struct conf::ZoneConfig>& zoneConfigs, 45 SensorManager& mgr, sdbusplus::bus::bus& modeControlBus) 46 { 47 std::unordered_map<int64_t, std::unique_ptr<PIDZone>> zones; 48 49 for (const auto& zi : zonePids) 50 { 51 auto zoneId = static_cast<int64_t>(zi.first); 52 /* The above shouldn't be necessary but is, and I am having trouble 53 * locating my notes on why. If I recall correctly it was casting it 54 * down to a byte in at least some cases causing weird behaviors. 55 */ 56 57 auto zoneConf = zoneConfigs.find(zoneId); 58 if (zoneConf == zoneConfigs.end()) 59 { 60 /* The Zone doesn't have a configuration, bail. */ 61 static constexpr auto err = 62 "Bailing during load, missing Zone Configuration"; 63 std::cerr << err << std::endl; 64 throw std::runtime_error(err); 65 } 66 67 const conf::PIDConf& pidConfig = zi.second; 68 69 auto zone = std::make_unique<PIDZone>( 70 zoneId, zoneConf->second.minThermalOutput, 71 zoneConf->second.failsafePercent, mgr, modeControlBus, 72 getControlPath(zi.first).c_str(), deferSignals); 73 74 std::cerr << "Zone Id: " << zone->getZoneID() << "\n"; 75 76 // For each PID create a Controller and a Sensor. 77 for (const auto& pit : pidConfig) 78 { 79 std::vector<std::string> inputs; 80 std::string name = pit.first; 81 const struct conf::ControllerInfo* info = &pit.second; 82 83 std::cerr << "PID name: " << name << "\n"; 84 85 /* 86 * TODO(venture): Need to check if input is known to the 87 * SensorManager. 88 */ 89 if (info->type == "fan") 90 { 91 for (const auto& i : info->inputs) 92 { 93 inputs.push_back(i); 94 zone->addFanInput(i); 95 } 96 97 auto pid = FanController::createFanPid(zone.get(), name, inputs, 98 info->pidInfo); 99 zone->addFanPID(std::move(pid)); 100 } 101 else if (isThermalType(info->type)) 102 { 103 for (const auto& i : info->inputs) 104 { 105 inputs.push_back(i); 106 zone->addThermalInput(i); 107 } 108 109 auto pid = ThermalController::createThermalPid( 110 zone.get(), name, inputs, info->setpoint, info->pidInfo, 111 getThermalType(info->type)); 112 113 zone->addThermalPID(std::move(pid)); 114 } 115 else if (info->type == "stepwise") 116 { 117 for (const auto& i : info->inputs) 118 { 119 inputs.push_back(i); 120 zone->addThermalInput(i); 121 } 122 auto stepwise = StepwiseController::createStepwiseController( 123 zone.get(), name, inputs, info->stepwiseInfo); 124 zone->addThermalPID(std::move(stepwise)); 125 } 126 127 std::cerr << "inputs: "; 128 for (const auto& i : inputs) 129 { 130 std::cerr << i << ", "; 131 } 132 std::cerr << "\n"; 133 } 134 135 zone->emit_object_added(); 136 zones[zoneId] = std::move(zone); 137 } 138 139 return zones; 140 } 141 142 } // namespace pid_control 143