1## GPIO-based Cable Presence Detection
2Author:
3  Chu Lin (linchuyuan@google.com)
4
5Created:
6  2021-07-29
7
8## Problem Description
9The intent of this new daemon design is to report GPIO-based cable presence
10status. IPMI currently doesn't support grouping discrete values and it could at
11most support 255 sensor IDs. On a systems with 25 cables, and 255 sensor IDs,
12taking up one sensor per slot would use 10% of the available space, and be a
13huge waste. Therefore, we need a solution to pack multiple presence states into
14less SDR IDs.
15
16## Background and References
171. https://www.intel.com/content/www/us/en/products/docs/servers/ipmi/ipmi-second-gen-interface-spec-v2-rev1-1.html
182. https://www.dmtf.org/sites/default/files/Redfish_Cable_Management_Proposal_WIP_04-2021.pdf
19
20## Requirements
211. The openbmc IPMI interface should support exposing cable presence states.
222. The OpenBMC dbus interface should be compatible with redfish
23
24## Proposed Design
25Inventory.Item.Cable will be introduced as a new dbus interface for querying
26cable objects. We will also need to introduce a new dbus daemon to collect
27Presence states. This new daemon will resIDe in openbmc/dbus-sensors. Its
28runtime configuration will be provIDed by EntityManager during startup. A
29proposed config file looks like the following:
30```
31{
32  "Exposes": [
33    {
34      "Name": "cable0",
35      "GpioLine": "osfp0",
36      "Polarity": "active_low",
37      "Type": "GPIOCableSensing",
38      "FaultLedGroup": [
39        "attention"
40      ]
41    },
42    {
43      "Name": "cable1",
44      "GpioLine": "osfp1",
45      "Polarity": "active_high",
46      "Type": "GPIOCableSensing",
47      "FaultLedGroup": [
48        "attention"
49      ]
50    }
51  ]
52}
53```
54The `Name` attribute is a unique name for each object from the config file.
55The `GpioLine` is the gpio line label from the device tree. The `Polarity`
56should tell the daemon whether it needs to revert the GPIO signal. Each entry
57from the config would get translated into one object on the dbus. In addition,
58the daemon polls the gpio presence signal for these objects in an interval of
5910 seconds. When the cable is not properly seated, the daemon will assert on
60the corresponding fault led group. This should cause the corresponding led to
61blink or to turn on base on how phosphor-led-manager is configured. No action
62is taken if FaultLedGroup is empty.
63
64On the IPMI sIDe, the presence states will be grouped into fewer SDR IDs in
65order to save SDR IDs for ipmi. Given the following example,
66```
67└─/xyz
68  └─/xyz/openbmc_project
69    └─/xyz/openbmc_project/inventory
70      └─/xyz/openbmc_project/inventory/item
71        └─/xyz/openbmc_project/inventory/item/cable0
72        └─/xyz/openbmc_project/inventory/item/cable1
73```
74In this example, we have both cable0 and cable1 and we expect to group them
75together. The grouping handler first removes all the trailing index from the
76SDR name. In this case, the SDR name is cable0 and cable1. After that, both
77cable0 and cable1 become cable. Therefore, objects with the same name after
78removing the trailing index indicates that they need to be grouped. After
79grouping, the new SDR name is cable[0-1]. The SDR name implies that this SDR
80has the presence state for cable0 and cable1. Meanwhile, the bit position
81for cable0 is 0 and the bit position for cable1 is 1. In the case of having
82more than 14 presence states, the group handler will automatically jump to use
83a new SDR. For example, if there are 20 cable indexed from 0 to 19, we
84shall see two SDRs. One is cable0-13. One is cable[14-19]. If the object path
85is not indexed by the user, it will take one SDR ID.
86```
87ipmitool sdr list event
88# /xyz/openbmc_project/inventory/item/cdfp0 to
89# /xyz/openbmc_project/inventory/item/cdfp3
90cdfp[0-3]        | Event-Only        | ns
91# /xyz/openbmc_project/inventory/item/osfp0 and
92# /xyz/openbmc_project/inventory/item/osfp1
93osfp[0-1]        | Event-Only        | ns
94```
95
96On the other hand, if the object name from the config file is not indexed. For
97example, `/xyz/openbmc_project/inventory/item/cable`. The group handler will not
98try to group it with anything and use 1 SDR ID for its presence state.
99See the following for an example output.
100```
101ipmitool sdr list event
102cdfp[0-3]        | Event-Only        | ns
103# /xyz/openbmc_project/inventory/item/osfp
104osfp             | Event-Only        | ns
105osfp[1-2]        | Event-Only        | ns
106```
107During the fetch operation, once the ipmi daemon receives the client request. It
108forwards the request to the dynamic ipmi commands. In the get method, the range
109string is extracted from the tailing square bracket. The original dbus path can
110be reconstructed given the index. Then, the SDR assertion value can be
111constructed after collecting the OperationalStatus from the dbus from each
112individual dbus objects.
113
114The design is also compatible with the Redfish daemon.  Redfish can call the
115GetSubTree method to list all the instances under the cable interface. In
116addition, Redfish doesn't have a limit of 256 SDR IDs. Therefore, no need to
117implement grouping mechanism. It should work out of the box.
118
119## Alternatives Considered
120
121* Explore the option of reporting the presence state via type12 record instead
122  of discrete sensors. The challenge here is that type12 record also has a limit
123  of 255 IDs. Meanwhile, it doesn't support stacking multiple presence states in
124  one ID.
125
126* We could also let the user define how to group different cables from config
127  file. However, this requires users to have a deep understanding of how ipmid
128  works. It is better if the ipmi daemon just takes care of this.
129
130* Instead of having a sleep-poll mechanism, it is better to have a event
131  listener on the gpio signals. However, the gpio_event_wait api requires all
132  the lines to come from the same chip. See
133  https://github.com/brgl/libgpiod/blob/cc23ef61f66d5a9055b0e9fbdcfe6744c8a637ae/lib/core.c#L993
134  We could spawn threads to listen to each chips but I don't think we should
135  increase the complexity of such a simple daemon.
136
137* The polling interval is 10 seconds. Is this too long/short for some other
138  projects? For now, let's make it a compiler option.
139
140* IPMI name string can only be 16 characters. Using square brackets would take
141  away 2 chars. However, using square brackets gives a better indication for the
142  start of the index string. Hence, the index string will be enclosed by square
143  bracket.
144
145
146## Testing
147Testing can be accomplished via automated or manual testing to verify that:
148
149* The presence state that is reported by GpioCableSevice is matching the result
150  from linux gpioget command.
151
152* Given the SDR name from `ipmitool sdr list event`, say cable[0-1], make sure
153  the zeroth bit is matching the presence state of object
154  `/xyz/openbmc_project/inventory/item/cable0` on the dbus and the first bit is
155  matching the state of object `/xyz/openbmc_project/inventory/item/cable`.
156
157* Unindex items from the config should have its own SDR ID. For example,
158  `/xyz/openbmc_project/inventory/item/cable` should not be grouped to another
159  group. Meanwhile, only the zero bit is used to report the presence state.
160
161* The state of the cable presence need to change with 10 seconds once a cable is
162  plug or unplug from the system.
163