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