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 112 private: 113 /** 114 * @brief Runs the contents of the action when the settle timer expires. 115 */ 116 void execute(); 117 118 /** 119 * @brief Constructs the PCIeCardMetadata object to load the PCIe card 120 * JSON files. 121 * 122 * @param[in] jsonObj - JSON configuration of this action 123 */ 124 void loadCardJSON(const json& jsonObj); 125 126 /** 127 * @brief Returns the D-Bus object path of the card plugged into 128 * the slot represented by the slotPath D-Bus path. 129 * 130 * @param[in] slotPath - The D-Bus path of the PCIe slot object. 131 * 132 * @return const std::string& - The card object path. 133 */ 134 const std::string& getCardFromSlot(const std::string& slotPath); 135 136 /** 137 * @brief Returns the floor index (or temp sensor name) for the 138 * card in the passed in slot. 139 * 140 * @param[in] slotPath - The D-Bus path of the PCIe slot object. 141 * 142 * @return optional<variant<int32_t, string>> 143 * - The floor index or true for has temp sensor if found, 144 * std::nullopt else. 145 */ 146 std::optional<std::variant<int32_t, bool>> 147 getFloorIndexFromSlot(const std::string& slotPath); 148 149 /** 150 * @brief Gets the hex PCIeDevice property value from the 151 * manager object cache. 152 * 153 * @param[in] objectPath - The card object path 154 * @param[in] propertyName - The property to read 155 * 156 * @return uint16_t The property value 157 */ 158 uint16_t getPCIeDeviceProperty(const std::string& objectPath, 159 const std::string& propertyName); 160 161 /* The PCIe card metadata manager */ 162 std::unique_ptr<PCIeCardMetadata> _cardMetadata; 163 164 /* Cache map of PCIe slot paths to their plugged card paths */ 165 std::unordered_map<std::string, std::string> _cards; 166 167 /* Cache of all objects with a PCIeDevice interface. */ 168 std::vector<std::string> _pcieDevices; 169 170 std::chrono::seconds _settleTime{0}; 171 172 /* Timer to wait for slot plugs to settle down before running action */ 173 std::unique_ptr<Timer> _settleTimer; 174 175 /* Last status printed so only new messages get recorded */ 176 std::string _lastStatus; 177 }; 178 179 } // namespace phosphor::fan::control::json 180