1 # GPIO based hardware inventory 2 3 Author: Alexander Hansen <alexander.hansen@9elements.com> 4 5 Other contributors: Chu Lin <linchuyuan@google.com> (through their previous 6 works), Amithash Prasad <amithash@meta.com> 7 8 Created: August 26, 2024 9 10 Reference: 11 [Chu Lin's gpio based cable presence detection](https://github.com/openbmc/docs/blob/46902afd6ebd20d1148379df99fe2c0c591f56ba/designs/gpio-based-cable-presence.md) 12 13 ## Problem Description 14 15 Due to increasing complexity of server designs and different configurations of 16 the same system being possible, there is a need for a simple way to detect the 17 presence of cards, cables and other connected entities which may or may not be 18 plugged into a system. A subset of these entities support presence detection via 19 gpios. This design focuses on those. 20 21 Connected entities detectable via other means are out of scope of this design. 22 23 ## Background and References 24 25 The existing design for the gpio based cable presence is partially implemented 26 and focuses on IPMI use-case. 27 28 [existing design by Chu Lin](https://github.com/openbmc/docs/blob/879601d92becfa1dbc082f487abfb5e0151a5091/designs/gpio-based-cable-presence.md) 29 30 Currently the way to do gpio based presence detection is via 31 phosphor-multi-gpio-presence and phosphor-inventory-manager. 32 33 The static inventory is declared and the inventory items are exposed at runtime 34 by phosphor-inventory-manager. 35 36 The presence daemon then toggles the 'Present' property on dbus interface 37 xyz.openbmc_project.Inventory.Item. 38 39 Additional item-specific properties are statically declared in the 40 phosphor-inventory-manager configuration. 41 42 An example of how this is currently done: 43 44 [presence daemon config](https://github.com/openbmc/openbmc/blob/1d438f68277cdb37e8062ae298402e9685882acb/meta-ibm/meta-sbp1/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-presence.json) 45 46 [phosphor-inventory-manager config](https://github.com/openbmc/openbmc/blob/1d438f68277cdb37e8062ae298402e9685882acb/meta-ibm/meta-sbp1/recipes-phosphor/inventory/static-inventory/static-inventory.yaml) 47 48 In the example we have inventory item **dimm_c0a1** which has following 49 phosphor-multi-gpio-presence configuration: 50 51 ```json 52 { 53 "Name": "DIMM_C0A1", 54 "LineName": "PLUG_DETECT_DIMM_C0A1", 55 "ActiveLow": true, 56 "Bias": "PULL_UP", 57 "Inventory": "/system/chassis/motherboard/dimm_c0a1" 58 } 59 ``` 60 61 and phosphor-inventory-manager configuration: 62 63 ```yaml 64 - name: Add DIMMs 65 description: > 66 Add the DIMM inventory path. 67 type: startup 68 actions: 69 - name: createObjects 70 objs: 71 /system/chassis/motherboard/dimm_c0a1: 72 xyz.openbmc_project.Inventory.Decorator.Replaceable: 73 FieldReplaceable: 74 value: true 75 type: boolean 76 xyz.openbmc_project.State.Decorator.OperationalStatus: 77 Functional: 78 value: true 79 type: boolean 80 xyz.openbmc_project.Inventory.Item: 81 PrettyName: 82 value: "DIMM C0A1" 83 type: string 84 Present: 85 value: false 86 type: boolean 87 xyz.openbmc_project.Inventory.Item.Dimm: 88 xyz.openbmc_project.Inventory.Decorator.LocationCode: 89 LocationCode: 90 value: "CPU0_DIMM_A1" 91 type: string 92 ``` 93 94 ## Requirements 95 96 - Support the gpio based detection of inventory items without static 97 configuration 98 99 - Allow configuration of the detectable inventory items through entity-manager 100 configuration 101 102 - e.g. cable 103 - e.g. fan board 104 - e.g. daughter board 105 - entity-manager should expose all required Inventory interfaces 106 - the properties for these inventory interfaces can be obtained through the 107 exposes record in the json configuration 108 109 - When a device is detected as present using the GPIO configuration published by 110 entity-manager, its probe match data is published to D-Bus, which triggers 111 entity-manager to publish the associated configuration. 112 113 - Support for re-use of presence information in PROBE statements 114 - detecting one entity as 'Present' should enable detecting other entities 115 based on that info 116 117 ## Proposed Design 118 119 The proposed design is to create a new daemon in the entity-manager repository, 120 which is 'gpio-presence-sensor'. 121 122 It can be inspired by implementations found in downstream forks such as the 123 [NVIDIA gpio presence sensor implementation](https://github.com/NVIDIA/dbus-sensors/blob/889abc1c9bfae9395690d1562f3e08453dfa12ba/src/GPIOPresenceSensorMain.cpp) 124 125 ### Diagram 126 127 ```mermaid 128 sequenceDiagram 129 130 participant PresenceDaemon 131 participant EM 132 participant AnyService 133 134 note over PresenceDaemon: cable0 plug 135 136 %% initial base configuration 137 138 activate EM 139 EM ->> EM: PROBE true on <br> xyz.openbmc_project.FruDevice <br> PRODUCT_PRODUCT_NAME=Yosemite V4 140 EM ->> PresenceDaemon: expose Configuration <br> xyz.openbmc_project.Configuration.GPIODeviceDetect <br> Name=com.meta.Hardware.Yv4.cable0 141 deactivate EM 142 activate PresenceDaemon 143 PresenceDaemon ->> PresenceDaemon: create dbus matcher <br> in case our configuration is removed 144 145 %% start forward flow 146 147 PresenceDaemon ->> PresenceDaemon: detect Device present <br> via GPIO Event 148 PresenceDaemon ->> EM: expose <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0 149 activate EM 150 deactivate PresenceDaemon 151 EM ->> EM: PROBE true on <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0 152 EM ->> AnyService: expose new Configuration <br> Example: Voltage Sensor 153 deactivate EM 154 155 activate AnyService 156 AnyService ->> AnyService: Example: <br> expose new Voltage Sensor 157 AnyService ->> AnyService: produce Sensor readings 158 159 %% start reverse flow 160 note over PresenceDaemon: cable0 unplug 161 162 activate PresenceDaemon 163 PresenceDaemon ->> PresenceDaemon: detect Device absent <br> via GPIO Event 164 PresenceDaemon ->> EM: remove <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0 165 deactivate PresenceDaemon 166 167 activate EM 168 EM ->> EM: PROBE false on <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0 169 EM ->> AnyService: remove new Configuration <br> Example: Voltage Sensor 170 deactivate EM 171 AnyService ->> AnyService: remove Sensor 172 deactivate AnyService 173 ``` 174 175 ### Forward flow summary 176 177 - EM exposes configuration for 'gpio-presence-sensor' 178 - 'gpio-presence-sensor' creates a dbus matcher to watch for removal of it's 179 configuration 180 - 'gpio-presence-sensor' uses gpios to detect hardware 181 - 'gpio-presence-sensor' creates a dbus interface when it detects hardware 182 - EM can probe new configuration files based on that dbus interface, via PROBE 183 statement 184 - EM exposes the new configuration for the detected hardware 185 186 ### Reverse flow summary 187 188 - 'gpio-presence-sensor' detects that the hardware is gone 189 - 'gpio-presence-sensor' takes down the respective dbus interface 190 - EM detects that via dbus matcher 191 - EM removes the configuration for that hardware from dbus 192 193 ### Reverse flow summary (removal of configuration) 194 195 - EM exposes configuration for 'gpio-presence-sensor' 196 - 'gpio-presence-sensor' creates a dbus matcher to watch for removal of it's 197 configuration 198 - 'gpio-presence-sensor' uses gpios to detect hardware 199 - 'gpio-presence-sensor' creates a dbus interface when it detects hardware 200 - EM removes the config for 'gpio-presence-sensor' 201 - 'gpio-presence-sensor' takes down any dbus interfaces it created for detecting 202 hardware 203 - EM detects that via dbus matcher 204 - EM removes the configuration for that hardware from dbus 205 206 ### Proposed DBus Interfaces 207 208 'gpio-presence-sensor' should consume configuration via dbus interface 209 210 `xyz.openbmc_project.Configuration.GPIODeviceDetect` 211 212 entity-manager already creates the needed dbus interfaces here. So there is no 213 need to make something new. 214 215 Below is a PDI yaml file to describe the proposed configuration interface: 216 217 ```yaml 218 description: > 219 Information to enable a daemon to probe hardware based on gpio values 220 properties: 221 - name: Name 222 type: string 223 description: > 224 Used by entity-manager to identify which hardware was detected. For 225 internal use by entity-manager. 226 - name: PresencePinNames 227 type: array[string] 228 description: > 229 Names of the gpio lines. 230 - name: PresencePinValues 231 type: array[uint64] 232 description: > 233 Values of the gpio lines for which the device is considered present. 234 Choosing 'uint64' instead of 'bool' here for compatibility with how EM 235 exposes configuration on dbus. 236 ``` 237 238 'gpio-presence-sensor' then exposes 239 `xyz.openbmc_project.Inventory.Source.DevicePresence` dbus interface of its own 240 if it detects the hardware: 241 242 ```yaml 243 description: > 244 Information for a daemon to expose if hardware has been detected based on 245 xyz.openbmc_project.Configuration.GPIODeviceDetect interface 246 properties: 247 - name: Name 248 type: string 249 description: > 250 Used by entity-manager to identify which hw was detected. For internal use 251 by entity-manager. 252 ``` 253 254 entity-manager can then consider the hardware as present and expose the 255 inventory interfaces for it. 256 257 ### Handling removal of the device 258 259 In case the gpio state changes, 'gpio-presence-sensor' can remove the 260 `xyz.openbmc_project.Inventory.Source.DevicePresence` interface and 261 entity-manager can have a dbus matcher for that, to then remove the respective 262 inventory items and any inventory items detected below it aswell. 263 264 ### Proposed changes in entity-manager 265 266 entity-manager needs to be extended to handle a new type 'GPIODeviceDetect' 267 Exposes record. It needs to then create the 268 `xyz.openbmc_project.Configuration.GPIODeviceDetect` dbus interface. 269 270 #### Proposed EM Configuration Schema 271 272 ```json 273 { 274 "$schema": "http://json-schema.org/draft-07/schema#", 275 "$defs": { 276 "GPIODeviceDetect": { 277 "type": "object", 278 "properties": { 279 "Name": { 280 "type": "string" 281 }, 282 "Type": { 283 "type": "string" 284 }, 285 "PresencePinNames": { 286 "type": "array", 287 "items": { 288 "type": "string" 289 } 290 }, 291 "PresencePinValues": { 292 "type": "array", 293 "items": { 294 "type": "number" 295 } 296 } 297 }, 298 "required": ["Name", "Type", "PresencePinNames", "PresencePinValues"] 299 } 300 } 301 } 302 ``` 303 304 ### Example EM Config Fragments 305 306 Below is an incomplete example of how such a config could look like. 307 308 The new part is the `"Type": "GPIODeviceDetect"` which is conveniently named the 309 same as the Dbus interface. 310 311 ```json 312 { 313 Exposes: 314 [ 315 { 316 "Name": "com.meta.Hardware.Yv4.cable0", 317 "PresencePinNames": ["presence-cable0"], 318 "PresencePinValues": [1], 319 "Type": "GPIODeviceDetect" 320 }, 321 { 322 "Name": "com.meta.Hardware.Yv4.ComputeCard", 323 "PresencePinNames": ["presence-slot0a", "presence-slot0b"], 324 "PresencePinValues": [0, 1], 325 "Type": "GPIODeviceDetect" 326 }, 327 { 328 "Name": "com.meta.Hardware.Yv4.SidecarExpansion", 329 "PresencePinNames": ["presence-slot0a", "presence-slot0b"], 330 "PresencePinValues": [1, 0], 331 "Type": "GPIODeviceDetect" 332 }, 333 { 334 "Name": "com.meta.Hardware.Yv4.AirBlocker", 335 "PresencePinNames": ["presence-slot0a", "presence-slot0b"], 336 "PresencePinValues": [1, 1], 337 "Type": "GPIODeviceDetect" 338 }, 339 { 340 "Name": "com.meta.Hardware.Yv4.fanboard0", 341 "PresencePinNames": ["presence-fanboard0"], 342 "PresencePinValues": [0], 343 "Type": "GPIODeviceDetect" 344 }, 345 ... 346 ], 347 ... 348 "Name": "Chassis", 349 "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'MYBOARDPRODUCT*'})", 350 "Type": "Board", 351 } 352 ``` 353 354 Another configuration can then contain additional records for the newly detected 355 e.g. fan board. 356 357 ```json 358 { 359 Exposes: 360 [ 361 { 362 "Address": "0x28", 363 "Bus": 5, 364 "EntityId": 7, 365 "EntityInstance": 0, 366 "Name": "fanboard_air_inlet", 367 "Name1": "fanboard_air_outlet", 368 "Type": "NCT7802" 369 }, 370 ... 371 ], 372 ... 373 "Name": "My Fan Board 0", 374 "Probe": "xyz.openbmc_project.Inventory.Source.DevicePresence({'Name': 'com.meta.Hardware.Yv4.fanboard0'})", 375 "Type": "Board", 376 } 377 ``` 378 379 ### Uniqueness of the "Name" property 380 381 There is a need to namespace configuration for devices probed via gpios, 382 according to their vendor or location in the system. "Name" is just a string but 383 it can be used to create namespacing with dots. This will prevent accidental 384 probing of unrelated configuration. 385 386 ## Alternatives Considered 387 388 - The existing approach with phosphor-inventory-manager and static configuration 389 Leaning away from that because it cannot support multiple different chassis 390 configurations in one fw image. 391 392 - Presence detection integrated into entity-manager. There already exists a 393 presence daemon, and it's an explicit non-goal of EM to implement any presence 394 detection. Maintainers have confirmed that EM should not implement this 395 feature internally. 396 397 - Another daemon which would expose inventory items based on EM configuration. 398 This would mean EM does not need to expose the item-specific inventory 399 interfaces and properties. 400 401 - Exposing the item-specific interfaces and properties in a generic way. This 402 means EM would lose any semantic knowledge of the entities it exposes and 403 become more like phosphor-inventory-manager 404 405 - Preventing duplication in case of multiple instances of e.g. fan 406 board/daughter board/cable through an additional variable besides "Name" that 407 could then be used in the the configuration file of the entity. This is 408 already covered partially by `$index` but `$index` is not stable and depends 409 on order and count of the devices probed successfully. But this feature is 410 left out intentionally here to limit the scope. So multiple instances of a 411 daughter board may need multiple slightly different configuration files. 412 413 - Comparing to Chu Lin's design, this design is not focused on the IPMI or 414 redfish use-case. It is separate from the external interface. It is assumed 415 the external interfaces can expose a cable inventory based on the 416 [cable dbus interface](https://github.com/openbmc/phosphor-dbus-interfaces/commit/3c5b76491afb8401627fc343077fe420f8a5e7f9) 417 which was created as part of Chu Lin's design. 418 419 - Comparing to Chu Lin's design, this design does not directly provide a cable 420 inventory. So there is another daemon or configuration decorator needed to 421 expose a cable inventory item. 422 423 - Comparing to Chu Lin's design, this design is not limited to cables. 424 425 ## Impacts 426 427 ### Organizational 428 429 - Does this repository require a new repository? No 430 - Who will be the initial maintainer(s) of this repository? 431 - Which repositories are expected to be modified to execute this design? 432 - entity-manager 433 - Make a list, and add listed repository maintainers to the gerrit review. 434 435 ## Testing 436 437 How will this be tested? How will this feature impact CI testing? 438 439 The feature can be tested in the entity-manager repository. We can use 440 dbus-run-session to run an actual entity-manager to provide the configuration or 441 simply provide a hardcoded configuration for 'gpio-presence-sensor'. For the 442 gpio interactions, we can use `CONFIG_GPIO_SIM` or alternatively abstract the 443 gpio interactions into a separate class which can then be stubbed. 444