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