xref: /openbmc/phosphor-pid-control/README.md (revision 5f59c0fd)
1# phosphor-pid-control
2
3[TOC]
4
5## Objective
6
7Develop a tray level fan control system that will use exhaust temperature and
8other machine temperature information to control fan speeds in order to keep
9machines within acceptable operating conditions.
10
11Effectively porting the Chromium EC thermal code to run on the BMC and use the
12OpenBMC dbus namespace and IPMI commands.
13
14## Background
15
16Recent server systems come with a general secondary processing system attached
17for the purpose of monitoring and control, generally referred to as a BMC[^2].
18There is a large effort to develop an open source framework for writing
19applications and control systems that will run on the BMC, known as
20OpenBMC[^3]<sup>,</sup>[^4]. Within Google the effort has been internalized
21(while also providing upstream pushes) as gBMC[^5]. The primary goal of OpenBMC
22is to provide support for remote and local system management through a REST
23interface, and also through IPMI[^6] tied together via the system dbus. OpenBMC
24provides many applications and daemons that we can leverage and improve.
25
26The BMC is wired such that it has direct access and control over many
27motherboard components, including fans and temperature sensors[^7]. Therefore,
28it is an ideal location to run a thermal control loop, similar to the EC.
29However, to upstream it will need to follow (as best as possible) the OpenBMC
30specifications for communicating and executing[^8].
31
32IPMI allows for OEM commands to provide custom information flow or system
33control with a BMC. OEM commands are already lined up for certain other accesses
34routed through the BMC, and can be upstreamed for others to use.
35
36## Overview
37
38The BMC will run a daemon that controls the fans by pre-defined zones. The
39application will use thermal control, such that each defined zone is kept
40within a range and adjusted based on thermal information provided from locally
41readable sensors as well as host-provided information over an IPMI OEM
42command.
43
44A system (or tray) will be broken out into one or more zones, specified via
45configuration files or dbus. Each zone will contain at least one fan and at
46least one temperature sensor and some device margins. The sensor data can
47be provided via sysfs, dbus, or through IPMI. In either case, default margins
48should be provided in case of failure or other unknown situation.
49
50The system will run a control loop for each zone with the attempt to maintain
51the temperature within that zone within the margin for the devices specified.
52
53## Detailed Design
54
55The software will run as a multi-threaded daemon that runs a control loop for
56each zone, and has a master thread which listens for dbus messages.  Each zone
57will require at least one fan that it exclusively controls, however, zones can
58 share temperature sensors.
59
60![Swampd Architecture](swampd_diagram.png "Swampd Architecture")
61
62In this figure the communications channels between swampd and ipmid and
63phosphor-hwmon are laid out.
64
65### OpenBMC Upstream
66
67To be upstreamed to OpenBMC for use on open-power systems, we need to follow the
68OpenBMC code style specification[^9] and leverage the dbus framework for reading
69sensors and fan control[^10].
70
71There is already a daemon, which given a configuration file for a hwmon device,
72will add it to the dbus objects namespace which handles queries for values such
73a temperature or fan speed and allows another process to control the fan
74speed[^11]. It is the goal to utilize this other daemon through dbus to read the
75onboard sensors and control the fans.
76
77Because of the present implementation of the dbus interfaces to require
78controlling the fans only via specifying the RPM target, whereas the driver
79we're using for Quanta-Q71l (the first system) only allows writing PWM.  This
80can be controlled either directly or via dbus.
81
82### Zone Specification
83
84A configuration file will need to exist for each board, likely in YAML[^12].
85Similar information will also be necessary for gsys, such that it knows what
86sensors to read and send to the BMC. Presently it does something similar with
87EC, so it shouldn't be unreasonable to do something similar.
88
89Each zone must have at least one fan that it exclusively controls. Each zone
90must have at least one temperature sensor, but they may be shared.
91
92The external devices specified in the zone must have default information as a
93fallback, while their current temperatures will be provided by gsys. Some
94devices adapt quickly and others slowly, and this distinction will need to be a
95factor and described in the configuration.
96
97The internal thermometers specified will be read via sysfs.
98
99#### A proposed configuration file:
100
101```
102{ZONEID}:
103  {PIDID}:
104    type: "fan" | "margin"
105    ipmi:
106      {IPMI_ID}
107      name: "fan1"
108      readpath: "/xyz/openbmc_project/sensors/fan_tach/fan1"
109      writepath: "/sys/class/hwmon/hwmon0/pwm0"
110    pidinfo:
111      samplerate: 0.1 // sample time in seconds
112      p_coeff: 0.01 // coefficient for proportional
113      i_coeff: 0.001 // coefficient for integral
114      integral_limit:
115        min: 0
116        max: 100
117      output_limit:
118        min: 0
119        max: 100
120      slew_negative: 0
121      slew_positive: 0
122  {PIDID}:
123    type: "margin"
124    ipmi:
125      {IPMI_ID}
126      name: "sluggish0"
127      readpath: "/xyz/openbmc_project/sensors/external/sluggish0"
128      writepath: ""
129    pidinfo:
130      samplerate: 1 // sample time in seconds
131      p_coeff: 94.0
132      i_coeff: 2.0
133      integral_limit:
134        min: 3000
135        max: 10000
136      output_limit:
137        min: 3000
138        max: 10000
139      slew_negative: 0
140      slew_positive: 0
141```
142
143### Chassis Delta
144
145Due to data center requirements, the delta between the outgoing air temperature
146and the environmental air temperature must be no greater than 15C.
147
148### IPMI Command Specification
149
150Gsys needs the ability to send to the BMC, the margin information on the devices
151that it knows how to read that the BMC cannot. There is no command in IPMI that
152currently supports this use-case, therefore it will be added as an OEM command.
153
154The state of the BMC readable temperature sensors can be read through normal
155IPMI commands and is already supported.
156
157#### OEM Set Control
158
159Gsys needs to be able to set the control of the thermal system to either
160automatic or manual. When manual, the daemon will effectively wait to be told to
161be put back in automatic mode. It is expected in this manual mode that something
162will be controlling the fans via the other commands.
163
164Manual mode is controlled by zone through the following OEM command:
165
166##### Request
167
168Byte | Purpose      | Value
169---- | ------------ | -----------------------------------------------------
170`00` | `netfn`      | `0x2e`
171`01` | `command`    | `0x04 (also using manual command)`
172`02` | `oem1`       | `0xcf`
173`03` | `oem2`       | `0xc2`
174`04` | `padding`    | `0x00`
175`05` | `SubCommand` | `Get or Set. Get == 0, Set == 1`
176`06` | `ZoneId`     |
177`07` | `Mode`       | `If Set, Value 1 == Manual Mode, 0 == Automatic Mode`
178
179##### Response
180
181Byte | Purpose   | Value
182---- | --------- | -----------------------------------------------------
183`02` | `oem1`    | `0xcf`
184`03` | `oem2`    | `0xc2`
185`04` | `padding` | `0x00`
186`07` | `Mode`    | `If Set, Value 1 == Manual Mode, 0 == Automatic Mode`
187
188#### OEM Get Failsafe Mode
189
190Gbmctool needs to be able to read back whether a zone is in failsafe mode. This
191setting is read-only because it's dynamically determined within Swampd per zone.
192
193Byte | Purpose      | Value
194---- | ------------ | ----------------------------------
195`00` | `netfn`      | `0x2e`
196`01` | `command`    | `0x04 (also using manual command)`
197`02` | `oem1`       | `0xcf`
198`03` | `oem2`       | `0xc2`
199`04` | `padding`    | `0x00`
200`05` | `SubCommand` | `Get == 2`
201`06` | `ZoneId`     |
202
203##### Response
204
205Byte | Purpose    | Value
206---- | ---------- | -----------------------------------------------
207`02` | `oem1`     | `0xcf`
208`03` | `oem2`     | `0xc2`
209`04` | `padding`  | `0x00`
210`07` | `failsafe` | `1 == in Failsafe Mode, 0 not in failsafe mode`
211
212#### Set Sensor Value
213
214Gsys needs to update the thermal controller with information not necessarily
215available to the BMC. This will comprise of a list of temperature (or margin?)
216sensors that are updated by the set sensor command. Because they don't represent
217real sensors in the system, the set sensor handler can simply broadcast the
218update as a properties update on dbus when it receives the command over IPMI.
219
220#### Set Fan PWM
221
222Gsys can override a specific fan's PWM when we implement the set sensor IPMI
223command pathway.
224
225#### Get Fan Tach
226
227Gsys can read fan_tach through the normal IPMI interface presently exported for
228sensors.
229
230### Sensor Update Loop
231
232The plan is to listen for fan_tach updates for each fan in a background thread.
233This will receive an update from phosphor-hwmon each time it updates any sensor
234it cares about.
235
236By default phosphor-hwmon reads each sensor in turn and then sleeps for 1
237second. We'll be updating phosphor-hwmon to sleep for a shorter period -- how
238short though is still TBD. We'll also be updating phosphor-hwmon to support pwm
239as a target.
240
241### Thermal Control Loops
242
243Each zone will require a control loop that monitors the associated thermals and
244controls the fan(s). The EC PID loop is designed to hit the fans 10 times per
245second to drive them to the desired value and read the sensors once per second.
246We'll be receiving sensor updates with such regularly, however, at present it
247takes ~0.13s to read all 8 fans. Which can't be read constantly without bringing
248the system to its knees -- in that all CPU cycles would be spent reading the
249fans. TBD on how frequently we'll be reading the fan sensors and the impact this
250will have.
251
252### Main Thread
253
254The main thread will manage the other threads, and process the initial
255configuration files. It will also register a dbus handler for the OEM message.
256
257### Enabling Logging
258
259By default, swampd isn't compiled to log information. To compile it for tuning,
260you'll need to add:
261
262```
263EXTRA_OEMAKE_append_YOUR_MACHINE = " CXXFLAGS='${CXXFLAGS} -D__TUNING_LOGGING__'"
264```
265
266To the recipe.
267
268## Project Information
269
270This project is designed to be a daemon running within the OpenBMC environment.
271It will use a well-defined configuration file to control the temperature of the
272tray components to keep them within operating conditions. It will require
273coordinate with gsys and OpenBMC. Providing a host-side service upstream to talk
274to the BMC is beyond the scope of this project.
275
276## Security Considerations
277
278A rogue client on the host could send invalid thermal information causing
279physical damage to the system. There will be an effort to sanity check all input
280from gsys to alleviate this concern.
281
282## Privacy Considerations
283
284This device holds no user data, however, you could profile the types of jobs
285executed on the server by watching its temperatures.
286
287## Testing Plan
288
289Testing individual code logic will be handled through unit-tests, however some
290pieces of code rely on abstractions such that we can swap out dbus with
291something encapsulated such that testing can be done without strictly running on
292a real system.
293
294Testing the system on real hardware will be performed to verify:
295
2961.  The fallback values are used when gsys isn't reporting.
2971.  The system behaves as expected given the information it reads.
298
299Unit-tests will provide that we know it validates information from gsys properly
300as well as handles difficult to reproduce edge cases.
301
302The testing of this project on real hardware can likely fold into the general
303gBMC testing planned.
304
305## Notes
306
307[^2]: BMC - Board Management Controller
308[^3]: with url https://github.com/openbmc/openbmc
309[^4]: with url https://github.com/facebook/openbmc
310[^5]: with url http://go/gbmc
311[^6]: with url
312    http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-second-gen-interface-spec-v2-rev1-1.html
313[^7]: Excluding temperature sensors on PCIe cards and other add-ons.
314[^8]: They prefer c++.
315[^9]: With url
316    https://github.com/openbmc/docs/blob/master/cpp-style-and-conventions.md
317[^10]: with url https://github.com/openbmc/phosphor-dbus-interfaces
318[^11]: with url https://github.com/openbmc/phosphor-hwmon
319[^12]: YAML appears to be the configuration language of choice for OpenBMC.
320