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