Add gpio-based cable presence detection doc
This is a attempt to implement a new dbus daemon to report cable
presence state
Signed-off-by: Chu Lin <linchuyuan@google.com>
Change-Id: Idb6e47f75504d097efe51f80b173c0d95cde872f
diff --git a/designs/gpio-based-cable-presence.md b/designs/gpio-based-cable-presence.md
new file mode 100644
index 0000000..1ed1cad
--- /dev/null
+++ b/designs/gpio-based-cable-presence.md
@@ -0,0 +1,154 @@
+## GPIO-based Cable Presence Detection
+Author:
+ Chu Lin (linchuyuan@google.com)
+Primary assignee:
+ Chu Lin (linchuyuan@google.com)
+Created:
+ 2021-07-29
+
+## Problem Description
+The intent of this new daemon design is to report GPIO-based cable presence
+status. IPMI currently doesn't support grouping discrete values and it could at
+most support 255 sensor IDs. On a systems with 25 cables, and 255 sensor IDs,
+taking up one sensor per slot would use 10% of the available space, and be a
+huge waste. Therefore, we need a solution to pack multiple presence states into
+less SDR IDs.
+
+## Background and References
+1. https://www.intel.com/content/www/us/en/products/docs/servers/ipmi/ipmi-second-gen-interface-spec-v2-rev1-1.html
+2. https://www.dmtf.org/sites/default/files/Redfish_Cable_Management_Proposal_WIP_04-2021.pdf
+
+## Requirements
+1. The openbmc IPMI interface should support exposing cable presence states.
+2. The OpenBMC dbus interface should be compatible with redfish
+
+## Proposed Design
+Inventory.Item.Cable will be introduced as a new dbus interface for querying
+cable objects. We will also need to introduce a new dbus daemon to collect
+Presence states. This new daemon will resIDe in openbmc/dbus-sensors. Its
+runtime configuration will be provIDed by EntityManager during startup. A
+proposed config file looks like the following:
+```
+{
+ "Exposes": [
+ {
+ "Name": "cable0",
+ "GpioLine": "osfp0",
+ "Polarity": "active_low",
+ "Type": "GPIOCableSensing"
+ },
+ {
+ "Name": "cable1",
+ "GpioLine": "osfp1",
+ "Polarity": "active_high",
+ "Type": "GPIOCableSensing"
+ }
+ ]
+}
+```
+The `Name` attribute is a unique name for each object from the config file.
+The `GpioLine` is the gpio line label from the device tree. The `Polarity`
+should tell the daemon whether it needs to revert the GPIO signal. Each entry
+from the config would get translated into one object on the dbus. In addition,
+the daemon polls the gpio presence signal for these objects in an interval of
+10 seconds.
+
+On the IPMI sIDe, the presence states will be grouped into fewer SDR IDs in
+order to save SDR IDs for ipmi. Given the following example,
+```
+└─/xyz
+ └─/xyz/openbmc_project
+ └─/xyz/openbmc_project/inventory
+ └─/xyz/openbmc_project/inventory/item
+ └─/xyz/openbmc_project/inventory/item/cable0
+ └─/xyz/openbmc_project/inventory/item/cable1
+```
+In this example, we have both cable0 and cable1 and we expect to group them
+together. The grouping handler first removes all the trailing index from the
+SDR name. In this case, the SDR name is cable0 and cable1. After that, both
+cable0 and cable1 become cable. Therefore, objects with the same name after
+removing the trailing index indicates that they need to be grouped. After
+grouping, the new SDR name is cable[0-1]. The SDR name implies that this SDR
+has the presence state for cable0 and cable1. Meanwhile, the bit position
+for cable0 is 0 and the bit position for cable1 is 1. In the case of having
+more than 14 presence states, the group handler will automatically jump to use
+a new SDR. For example, if there are 20 cable indexed from 0 to 19, we
+shall see two SDRs. One is cable0-13. One is cable[14-19]. If the object path
+is not indexed by the user, it will take one SDR ID.
+```
+ipmitool sdr list event
+# /xyz/openbmc_project/inventory/item/cdfp0 to
+# /xyz/openbmc_project/inventory/item/cdfp3
+cdfp[0-3] | Event-Only | ns
+# /xyz/openbmc_project/inventory/item/osfp0 and
+# /xyz/openbmc_project/inventory/item/osfp1
+osfp[0-1] | Event-Only | ns
+```
+
+On the other hand, if the object name from the config file is not indexed. For
+exmaple, `/xyz/openbmc_project/inventory/item/cable`. The group handler will not
+try to group it with anything and use 1 SDR ID for its presence state.
+See the following for an example output.
+```
+ipmitool sdr list event
+cdfp[0-3] | Event-Only | ns
+# /xyz/openbmc_project/inventory/item/osfp
+osfp | Event-Only | ns
+osfp[1-2] | Event-Only | ns
+```
+During the fetch operation, once the ipmi daemon receives the client request. It
+forwards the request to the dynamic ipmi commands. In the get method, the range
+string is extracted from the tailing square bracket. The original dbus path can
+be reconstructed given the index. Then, the SDR assertion value can be
+constructed after collecting the OperationalStatus from the dbus from each
+individual dbus objects.
+
+The design is also compatible with the Redfish daemon. Redfish can call the
+GetSubTree method to list all the instances under the cable interface. In
+addition, Redfish doesn't have a limit of 256 SDR IDs. Therefore, no need to
+implement grouping mechanism. It should work out of the box.
+
+## Alternatives Considered
+
+* Explore the option of reporting the presence state via type12 record instead
+ of discrete sensors. The challenge here is that type12 record also has a limit
+ of 255 IDs. Meanwhile, it doesn't support stacking multiple presence states in
+ one ID.
+
+* We could also let the user define how to group different cables from config
+ file. However, this requires users to have a deep understanding of how ipmid
+ works. It is better if the ipmi daemon just takes care of this.
+
+* Instead of having a sleep-poll mechanism, it is better to have a event
+ listener on the gpio signals. However, the gpio_event_wait api requires all
+ the lines to come from the same chip. See
+ https://github.com/brgl/libgpiod/blob/cc23ef61f66d5a9055b0e9fbdcfe6744c8a637ae/lib/core.c#L993
+ We could spawn threads to listen to each chips but I don't think we should
+ increase the complexity of such a simple daemon.
+
+* The polling interval is 10 seconds. Is this too long/short for some other
+ projects? For now, let's make it a compiler option.
+
+* IPMI name string can only be 16 characters. Using square brackets would take
+ away 2 chars. However, using square brackets gives a better indication for the
+ start of the index string. Hence, the index string will be enclosed by square
+ bracket.
+
+
+## Testing
+Testing can be accomplished via automated or manual testing to verify that:
+
+* The presence state that is reported by GpioCableSevice is matching the result
+ from linux gpioget command.
+
+* Given the SDR name from `ipmitool sdr list event`, say cable[0-1], make sure
+ the zeroth bit is matching the presence state of object
+ `/xyz/openbmc_project/inventory/item/cable0` on the dbus and the first bit is
+ matching the state of object `/xyz/openbmc_project/inventory/item/cable`.
+
+* Unindex items from the config should have its own SDR ID. For example,
+ `/xyz/openbmc_project/inventory/item/cable` should not be grouped to another
+ group. Meanwhile, only the zero bit is used to report the presence state.
+
+* The state of the cable presence need to change with 10 seconds once a cable is
+ plug or unplug from the system.