1 /** 2 * Copyright © 2021 IBM Corporation 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 #pragma once 17 18 #include "../zone.hpp" 19 #include "action.hpp" 20 #include "group.hpp" 21 #include "utils/pcie_card_metadata.hpp" 22 23 #include <nlohmann/json.hpp> 24 25 namespace phosphor::fan::control::json 26 { 27 28 using json = nlohmann::json; 29 30 class Manager; 31 32 /** 33 * @class PCIeCardFloors - Action to set the PCIe card floor index parameter 34 * based on the PCIe cards plugged in the system. 35 * 36 * - Loads PCIe card metadata files using the PCIeCardMetadata class. 37 * - Watches for PCIe slots to be powered on (or off). 38 * - Reads four properties off of the PCIeDevice interface on the powered 39 * on cards. 40 * - Looks up the floor index for the card by calling PCIeCardMetadata::lookup 41 * and passing in the PCIeDevice properties. 42 * - Sets the pcie_floor_index parameter with the highest floor index found. 43 * - If no PCIe cards are found, it removes the parameter. 44 * - If a card isn't recognized, it's ignored since it isn't considered a 45 * hot card. 46 * - If a powered on card has its own temperature sensor, then it doesn't 47 * have a floor index. 48 * - Since the slot powered on indications are all sent at once, it has a 49 * small delay that gets started in each run() call that must expire 50 * before the body of the action is run, so it only runs once. 51 * 52 * The JSON configuration has two entries: 53 * { 54 * "settle_time": <time in s> 55 * "use_config_specific_files": <true/false> 56 * } 57 * 58 * settle_time: 59 * - Specifies how long to wait after run() is called before actually 60 * running the action as a flurry of propertiesChanged signals 61 * that trigger the action tend to come at once. 62 * - Optional. If not specified it defaults to zero. 63 * 64 * use_config_specific_files: 65 * - If true, will look for 'pcie_cards.json' files in the system 66 * specific directories. 67 * - See PCIeCardMetadata for details. 68 */ 69 class PCIeCardFloors : public ActionBase, public ActionRegister<PCIeCardFloors> 70 { 71 public: 72 /* Name of this action */ 73 static constexpr auto name = "pcie_card_floors"; 74 75 PCIeCardFloors() = delete; 76 PCIeCardFloors(const PCIeCardFloors&) = delete; 77 PCIeCardFloors(PCIeCardFloors&&) = delete; 78 PCIeCardFloors& operator=(const PCIeCardFloors&) = delete; 79 PCIeCardFloors& operator=(PCIeCardFloors&&) = delete; 80 ~PCIeCardFloors() = default; 81 82 /** 83 * @brief Read in the action configuration 84 * 85 * @param[in] jsonObj - JSON configuration of this action 86 * @param[in] groups - Groups of dbus objects the action uses 87 */ 88 PCIeCardFloors(const json& jsonObj, const std::vector<Group>& groups); 89 90 /** 91 * @brief Run the action. 92 * 93 * Starts/restarts the settle timer and then calls execute() 94 * when it expires. Done to handle the flood of slot powered 95 * on/off signals. 96 * 97 * @param[in] zone - Zone to run the action on 98 */ 99 void run(Zone& zone) override; 100 101 /** 102 * @brief Set the name of the owning Event. 103 * 104 * In the base class it's appending it to the action's unique name. Don't 105 * do it for this action since there's only one instance of it so no need 106 * to distinguish it from ones under different events and also it just 107 * makes it uglier in the flight recorder. 108 */ 109 void setEventName(const std::string& /*name*/) override {} 110 111 private: 112 /** 113 * @brief Runs the contents of the action when the settle timer expires. 114 */ 115 void execute(); 116 117 /** 118 * @brief Constructs the PCIeCardMetadata object to load the PCIe card 119 * JSON files. 120 * 121 * @param[in] jsonObj - JSON configuration of this action 122 */ 123 void loadCardJSON(const json& jsonObj); 124 125 /** 126 * @brief Returns the D-Bus object path of the card plugged into 127 * the slot represented by the slotPath D-Bus path. 128 * 129 * @param[in] slotPath - The D-Bus path of the PCIe slot object. 130 * 131 * @return const std::string& - The card object path. 132 */ 133 const std::string& getCardFromSlot(const std::string& slotPath); 134 135 /** 136 * @brief Returns the floor index (or temp sensor name) for the 137 * card in the passed in slot. 138 * 139 * @param[in] slotPath - The D-Bus path of the PCIe slot object. 140 * 141 * @return optional<variant<int32_t, string>> 142 * - The floor index or true for has temp sensor if found, 143 * std::nullopt else. 144 */ 145 std::optional<std::variant<int32_t, bool>> 146 getFloorIndexFromSlot(const std::string& slotPath); 147 148 /** 149 * @brief Gets the hex PCIeDevice property value from the 150 * manager object cache. 151 * 152 * @param[in] objectPath - The card object path 153 * @param[in] propertyName - The property to read 154 * 155 * @return uint16_t The property value 156 */ 157 uint16_t getPCIeDeviceProperty(const std::string& objectPath, 158 const std::string& propertyName); 159 160 /* The PCIe card metadata manager */ 161 std::unique_ptr<PCIeCardMetadata> _cardMetadata; 162 163 /* Cache map of PCIe slot paths to their plugged card paths */ 164 std::unordered_map<std::string, std::string> _cards; 165 166 /* Cache of all objects with a PCIeDevice interface. */ 167 std::vector<std::string> _pcieDevices; 168 169 std::chrono::seconds _settleTime{0}; 170 171 /* Timer to wait for slot plugs to settle down before running action */ 172 std::unique_ptr<Timer> _settleTimer; 173 174 /* Last status printed so only new messages get recorded */ 175 std::string _lastStatus; 176 }; 177 178 } // namespace phosphor::fan::control::json 179