xref: /openbmc/linux/Documentation/driver-api/surface_aggregator/internal.rst (revision 762f99f4f3cb41a775b5157dd761217beba65873)
18d779282SMaximilian Luz.. SPDX-License-Identifier: GPL-2.0+
28d779282SMaximilian Luz
38d779282SMaximilian Luz.. |ssh_ptl| replace:: :c:type:`struct ssh_ptl <ssh_ptl>`
48d779282SMaximilian Luz.. |ssh_ptl_submit| replace:: :c:func:`ssh_ptl_submit`
58d779282SMaximilian Luz.. |ssh_ptl_cancel| replace:: :c:func:`ssh_ptl_cancel`
68d779282SMaximilian Luz.. |ssh_ptl_shutdown| replace:: :c:func:`ssh_ptl_shutdown`
78d779282SMaximilian Luz.. |ssh_ptl_rx_rcvbuf| replace:: :c:func:`ssh_ptl_rx_rcvbuf`
88d779282SMaximilian Luz.. |ssh_rtl| replace:: :c:type:`struct ssh_rtl <ssh_rtl>`
98d779282SMaximilian Luz.. |ssh_rtl_submit| replace:: :c:func:`ssh_rtl_submit`
108d779282SMaximilian Luz.. |ssh_rtl_cancel| replace:: :c:func:`ssh_rtl_cancel`
118d779282SMaximilian Luz.. |ssh_rtl_shutdown| replace:: :c:func:`ssh_rtl_shutdown`
128d779282SMaximilian Luz.. |ssh_packet| replace:: :c:type:`struct ssh_packet <ssh_packet>`
138d779282SMaximilian Luz.. |ssh_packet_get| replace:: :c:func:`ssh_packet_get`
148d779282SMaximilian Luz.. |ssh_packet_put| replace:: :c:func:`ssh_packet_put`
158d779282SMaximilian Luz.. |ssh_packet_ops| replace:: :c:type:`struct ssh_packet_ops <ssh_packet_ops>`
168d779282SMaximilian Luz.. |ssh_packet_base_priority| replace:: :c:type:`enum ssh_packet_base_priority <ssh_packet_base_priority>`
178d779282SMaximilian Luz.. |ssh_packet_flags| replace:: :c:type:`enum ssh_packet_flags <ssh_packet_flags>`
188d779282SMaximilian Luz.. |SSH_PACKET_PRIORITY| replace:: :c:func:`SSH_PACKET_PRIORITY`
198d779282SMaximilian Luz.. |ssh_frame| replace:: :c:type:`struct ssh_frame <ssh_frame>`
208d779282SMaximilian Luz.. |ssh_command| replace:: :c:type:`struct ssh_command <ssh_command>`
218d779282SMaximilian Luz.. |ssh_request| replace:: :c:type:`struct ssh_request <ssh_request>`
228d779282SMaximilian Luz.. |ssh_request_get| replace:: :c:func:`ssh_request_get`
238d779282SMaximilian Luz.. |ssh_request_put| replace:: :c:func:`ssh_request_put`
248d779282SMaximilian Luz.. |ssh_request_ops| replace:: :c:type:`struct ssh_request_ops <ssh_request_ops>`
258d779282SMaximilian Luz.. |ssh_request_init| replace:: :c:func:`ssh_request_init`
268d779282SMaximilian Luz.. |ssh_request_flags| replace:: :c:type:`enum ssh_request_flags <ssh_request_flags>`
278d779282SMaximilian Luz.. |ssam_controller| replace:: :c:type:`struct ssam_controller <ssam_controller>`
288d779282SMaximilian Luz.. |ssam_device| replace:: :c:type:`struct ssam_device <ssam_device>`
298d779282SMaximilian Luz.. |ssam_device_driver| replace:: :c:type:`struct ssam_device_driver <ssam_device_driver>`
308d779282SMaximilian Luz.. |ssam_client_bind| replace:: :c:func:`ssam_client_bind`
318d779282SMaximilian Luz.. |ssam_client_link| replace:: :c:func:`ssam_client_link`
328d779282SMaximilian Luz.. |ssam_request_sync| replace:: :c:type:`struct ssam_request_sync <ssam_request_sync>`
338d779282SMaximilian Luz.. |ssam_event_registry| replace:: :c:type:`struct ssam_event_registry <ssam_event_registry>`
348d779282SMaximilian Luz.. |ssam_event_id| replace:: :c:type:`struct ssam_event_id <ssam_event_id>`
358d779282SMaximilian Luz.. |ssam_nf| replace:: :c:type:`struct ssam_nf <ssam_nf>`
368d779282SMaximilian Luz.. |ssam_nf_refcount_inc| replace:: :c:func:`ssam_nf_refcount_inc`
378d779282SMaximilian Luz.. |ssam_nf_refcount_dec| replace:: :c:func:`ssam_nf_refcount_dec`
388d779282SMaximilian Luz.. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register`
398d779282SMaximilian Luz.. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister`
408d779282SMaximilian Luz.. |ssam_cplt| replace:: :c:type:`struct ssam_cplt <ssam_cplt>`
418d779282SMaximilian Luz.. |ssam_event_queue| replace:: :c:type:`struct ssam_event_queue <ssam_event_queue>`
428d779282SMaximilian Luz.. |ssam_request_sync_submit| replace:: :c:func:`ssam_request_sync_submit`
438d779282SMaximilian Luz
448d779282SMaximilian Luz=====================
458d779282SMaximilian LuzCore Driver Internals
468d779282SMaximilian Luz=====================
478d779282SMaximilian Luz
488d779282SMaximilian LuzArchitectural overview of the Surface System Aggregator Module (SSAM) core
498d779282SMaximilian Luzand Surface Serial Hub (SSH) driver. For the API documentation, refer to:
508d779282SMaximilian Luz
518d779282SMaximilian Luz.. toctree::
528d779282SMaximilian Luz   :maxdepth: 2
538d779282SMaximilian Luz
548d779282SMaximilian Luz   internal-api
558d779282SMaximilian Luz
568d779282SMaximilian Luz
578d779282SMaximilian LuzOverview
588d779282SMaximilian Luz========
598d779282SMaximilian Luz
608d779282SMaximilian LuzThe SSAM core implementation is structured in layers, somewhat following the
618d779282SMaximilian LuzSSH protocol structure:
628d779282SMaximilian Luz
638d779282SMaximilian LuzLower-level packet transport is implemented in the *packet transport layer
648d779282SMaximilian Luz(PTL)*, directly building on top of the serial device (serdev)
658d779282SMaximilian Luzinfrastructure of the kernel. As the name indicates, this layer deals with
668d779282SMaximilian Luzthe packet transport logic and handles things like packet validation, packet
678d779282SMaximilian Luzacknowledgment (ACKing), packet (retransmission) timeouts, and relaying
688d779282SMaximilian Luzpacket payloads to higher-level layers.
698d779282SMaximilian Luz
708d779282SMaximilian LuzAbove this sits the *request transport layer (RTL)*. This layer is centered
718d779282SMaximilian Luzaround command-type packet payloads, i.e. requests (sent from host to EC),
728d779282SMaximilian Luzresponses of the EC to those requests, and events (sent from EC to host).
738d779282SMaximilian LuzIt, specifically, distinguishes events from request responses, matches
748d779282SMaximilian Luzresponses to their corresponding requests, and implements request timeouts.
758d779282SMaximilian Luz
768d779282SMaximilian LuzThe *controller* layer is building on top of this and essentially decides
778d779282SMaximilian Luzhow request responses and, especially, events are dealt with. It provides an
788d779282SMaximilian Luzevent notifier system, handles event activation/deactivation, provides a
798d779282SMaximilian Luzworkqueue for event and asynchronous request completion, and also manages
808d779282SMaximilian Luzthe message counters required for building command messages (``SEQ``,
818d779282SMaximilian Luz``RQID``). This layer basically provides a fundamental interface to the SAM
828d779282SMaximilian LuzEC for use in other kernel drivers.
838d779282SMaximilian Luz
848d779282SMaximilian LuzWhile the controller layer already provides an interface for other kernel
858d779282SMaximilian Luzdrivers, the client *bus* extends this interface to provide support for
868d779282SMaximilian Luznative SSAM devices, i.e. devices that are not defined in ACPI and not
878d779282SMaximilian Luzimplemented as platform devices, via |ssam_device| and |ssam_device_driver|
888d779282SMaximilian Luzsimplify management of client devices and client drivers.
898d779282SMaximilian Luz
90*bbbaf226SMauro Carvalho ChehabRefer to Documentation/driver-api/surface_aggregator/client.rst for
91*bbbaf226SMauro Carvalho Chehabdocumentation regarding the client device/driver API and interface options
92*bbbaf226SMauro Carvalho Chehabfor other kernel drivers. It is recommended to familiarize oneself with
93*bbbaf226SMauro Carvalho Chehabthat chapter and the Documentation/driver-api/surface_aggregator/ssh.rst
94*bbbaf226SMauro Carvalho Chehabbefore continuing with the architectural overview below.
958d779282SMaximilian Luz
968d779282SMaximilian Luz
978d779282SMaximilian LuzPacket Transport Layer
988d779282SMaximilian Luz======================
998d779282SMaximilian Luz
1008d779282SMaximilian LuzThe packet transport layer is represented via |ssh_ptl| and is structured
1018d779282SMaximilian Luzaround the following key concepts:
1028d779282SMaximilian Luz
1038d779282SMaximilian LuzPackets
1048d779282SMaximilian Luz-------
1058d779282SMaximilian Luz
1068d779282SMaximilian LuzPackets are the fundamental transmission unit of the SSH protocol. They are
1078d779282SMaximilian Luzmanaged by the packet transport layer, which is essentially the lowest layer
1088d779282SMaximilian Luzof the driver and is built upon by other components of the SSAM core.
1098d779282SMaximilian LuzPackets to be transmitted by the SSAM core are represented via |ssh_packet|
1108d779282SMaximilian Luz(in contrast, packets received by the core do not have any specific
1118d779282SMaximilian Luzstructure and are managed entirely via the raw |ssh_frame|).
1128d779282SMaximilian Luz
1138d779282SMaximilian LuzThis structure contains the required fields to manage the packet inside the
1148d779282SMaximilian Luztransport layer, as well as a reference to the buffer containing the data to
1158d779282SMaximilian Luzbe transmitted (i.e. the message wrapped in |ssh_frame|). Most notably, it
1168d779282SMaximilian Luzcontains an internal reference count, which is used for managing its
1178d779282SMaximilian Luzlifetime (accessible via |ssh_packet_get| and |ssh_packet_put|). When this
1188d779282SMaximilian Luzcounter reaches zero, the ``release()`` callback provided to the packet via
1198d779282SMaximilian Luzits |ssh_packet_ops| reference is executed, which may then deallocate the
1208d779282SMaximilian Luzpacket or its enclosing structure (e.g. |ssh_request|).
1218d779282SMaximilian Luz
1228d779282SMaximilian LuzIn addition to the ``release`` callback, the |ssh_packet_ops| reference also
1238d779282SMaximilian Luzprovides a ``complete()`` callback, which is run once the packet has been
1248d779282SMaximilian Luzcompleted and provides the status of this completion, i.e. zero on success
1258d779282SMaximilian Luzor a negative errno value in case of an error. Once the packet has been
1268d779282SMaximilian Luzsubmitted to the packet transport layer, the ``complete()`` callback is
1278d779282SMaximilian Luzalways guaranteed to be executed before the ``release()`` callback, i.e. the
1288d779282SMaximilian Luzpacket will always be completed, either successfully, with an error, or due
1298d779282SMaximilian Luzto cancellation, before it will be released.
1308d779282SMaximilian Luz
1318d779282SMaximilian LuzThe state of a packet is managed via its ``state`` flags
1328d779282SMaximilian Luz(|ssh_packet_flags|), which also contains the packet type. In particular,
1338d779282SMaximilian Luzthe following bits are noteworthy:
1348d779282SMaximilian Luz
1358d779282SMaximilian Luz* ``SSH_PACKET_SF_LOCKED_BIT``: This bit is set when completion, either
1368d779282SMaximilian Luz  through error or success, is imminent. It indicates that no further
1378d779282SMaximilian Luz  references of the packet should be taken and any existing references
1388d779282SMaximilian Luz  should be dropped as soon as possible. The process setting this bit is
1398d779282SMaximilian Luz  responsible for removing any references to this packet from the packet
1408d779282SMaximilian Luz  queue and pending set.
1418d779282SMaximilian Luz
1428d779282SMaximilian Luz* ``SSH_PACKET_SF_COMPLETED_BIT``: This bit is set by the process running the
1438d779282SMaximilian Luz  ``complete()`` callback and is used to ensure that this callback only runs
1448d779282SMaximilian Luz  once.
1458d779282SMaximilian Luz
1468d779282SMaximilian Luz* ``SSH_PACKET_SF_QUEUED_BIT``: This bit is set when the packet is queued on
1478d779282SMaximilian Luz  the packet queue and cleared when it is dequeued.
1488d779282SMaximilian Luz
1498d779282SMaximilian Luz* ``SSH_PACKET_SF_PENDING_BIT``: This bit is set when the packet is added to
1508d779282SMaximilian Luz  the pending set and cleared when it is removed from it.
1518d779282SMaximilian Luz
1528d779282SMaximilian LuzPacket Queue
1538d779282SMaximilian Luz------------
1548d779282SMaximilian Luz
1558d779282SMaximilian LuzThe packet queue is the first of the two fundamental collections in the
1568d779282SMaximilian Luzpacket transport layer. It is a priority queue, with priority of the
1578d779282SMaximilian Luzrespective packets based on the packet type (major) and number of tries
1588d779282SMaximilian Luz(minor). See |SSH_PACKET_PRIORITY| for more details on the priority value.
1598d779282SMaximilian Luz
1608d779282SMaximilian LuzAll packets to be transmitted by the transport layer must be submitted to
1618d779282SMaximilian Luzthis queue via |ssh_ptl_submit|. Note that this includes control packets
1628d779282SMaximilian Luzsent by the transport layer itself. Internally, data packets can be
1638d779282SMaximilian Luzre-submitted to this queue due to timeouts or NAK packets sent by the EC.
1648d779282SMaximilian Luz
1658d779282SMaximilian LuzPending Set
1668d779282SMaximilian Luz-----------
1678d779282SMaximilian Luz
1688d779282SMaximilian LuzThe pending set is the second of the two fundamental collections in the
1698d779282SMaximilian Luzpacket transport layer. It stores references to packets that have already
1708d779282SMaximilian Luzbeen transmitted, but wait for acknowledgment (e.g. the corresponding ACK
1718d779282SMaximilian Luzpacket) by the EC.
1728d779282SMaximilian Luz
1738d779282SMaximilian LuzNote that a packet may both be pending and queued if it has been
1748d779282SMaximilian Luzre-submitted due to a packet acknowledgment timeout or NAK. On such a
1758d779282SMaximilian Luzre-submission, packets are not removed from the pending set.
1768d779282SMaximilian Luz
1778d779282SMaximilian LuzTransmitter Thread
1788d779282SMaximilian Luz------------------
1798d779282SMaximilian Luz
1808d779282SMaximilian LuzThe transmitter thread is responsible for most of the actual work regarding
1818d779282SMaximilian Luzpacket transmission. In each iteration, it (waits for and) checks if the
1828d779282SMaximilian Luznext packet on the queue (if any) can be transmitted and, if so, removes it
1838d779282SMaximilian Luzfrom the queue and increments its counter for the number of transmission
1848d779282SMaximilian Luzattempts, i.e. tries. If the packet is sequenced, i.e. requires an ACK by
1858d779282SMaximilian Luzthe EC, the packet is added to the pending set. Next, the packet's data is
1868d779282SMaximilian Luzsubmitted to the serdev subsystem. In case of an error or timeout during
1878d779282SMaximilian Luzthis submission, the packet is completed by the transmitter thread with the
1888d779282SMaximilian Luzstatus value of the callback set accordingly. In case the packet is
1898d779282SMaximilian Luzunsequenced, i.e. does not require an ACK by the EC, the packet is completed
1908d779282SMaximilian Luzwith success on the transmitter thread.
1918d779282SMaximilian Luz
1928d779282SMaximilian LuzTransmission of sequenced packets is limited by the number of concurrently
1938d779282SMaximilian Luzpending packets, i.e. a limit on how many packets may be waiting for an ACK
194*bbbaf226SMauro Carvalho Chehabfrom the EC in parallel. This limit is currently set to one (see
195*bbbaf226SMauro Carvalho ChehabDocumentation/driver-api/surface_aggregator/ssh.rst for the reasoning behind
196*bbbaf226SMauro Carvalho Chehabthis). Control packets (i.e. ACK and NAK) can always be transmitted.
1978d779282SMaximilian Luz
1988d779282SMaximilian LuzReceiver Thread
1998d779282SMaximilian Luz---------------
2008d779282SMaximilian Luz
2018d779282SMaximilian LuzAny data received from the EC is put into a FIFO buffer for further
2028d779282SMaximilian Luzprocessing. This processing happens on the receiver thread. The receiver
2038d779282SMaximilian Luzthread parses and validates the received message into its |ssh_frame| and
2048d779282SMaximilian Luzcorresponding payload. It prepares and submits the necessary ACK (and on
2058d779282SMaximilian Luzvalidation error or invalid data NAK) packets for the received messages.
2068d779282SMaximilian Luz
2078d779282SMaximilian LuzThis thread also handles further processing, such as matching ACK messages
2088d779282SMaximilian Luzto the corresponding pending packet (via sequence ID) and completing it, as
2098d779282SMaximilian Luzwell as initiating re-submission of all currently pending packets on
2108d779282SMaximilian Luzreceival of a NAK message (re-submission in case of a NAK is similar to
2118d779282SMaximilian Luzre-submission due to timeout, see below for more details on that). Note that
2128d779282SMaximilian Luzthe successful completion of a sequenced packet will always run on the
2138d779282SMaximilian Luzreceiver thread (whereas any failure-indicating completion will run on the
2148d779282SMaximilian Luzprocess where the failure occurred).
2158d779282SMaximilian Luz
2168d779282SMaximilian LuzAny payload data is forwarded via a callback to the next upper layer, i.e.
2178d779282SMaximilian Luzthe request transport layer.
2188d779282SMaximilian Luz
2198d779282SMaximilian LuzTimeout Reaper
2208d779282SMaximilian Luz--------------
2218d779282SMaximilian Luz
2228d779282SMaximilian LuzThe packet acknowledgment timeout is a per-packet timeout for sequenced
2238d779282SMaximilian Luzpackets, started when the respective packet begins (re-)transmission (i.e.
2248d779282SMaximilian Luzthis timeout is armed once per transmission attempt on the transmitter
2258d779282SMaximilian Luzthread). It is used to trigger re-submission or, when the number of tries
2268d779282SMaximilian Luzhas been exceeded, cancellation of the packet in question.
2278d779282SMaximilian Luz
2288d779282SMaximilian LuzThis timeout is handled via a dedicated reaper task, which is essentially a
2298d779282SMaximilian Luzwork item (re-)scheduled to run when the next packet is set to time out. The
2308d779282SMaximilian Luzwork item then checks the set of pending packets for any packets that have
2318d779282SMaximilian Luzexceeded the timeout and, if there are any remaining packets, re-schedules
2328d779282SMaximilian Luzitself to the next appropriate point in time.
2338d779282SMaximilian Luz
2348d779282SMaximilian LuzIf a timeout has been detected by the reaper, the packet will either be
2358d779282SMaximilian Luzre-submitted if it still has some remaining tries left, or completed with
2368d779282SMaximilian Luz``-ETIMEDOUT`` as status if not. Note that re-submission, in this case and
2378d779282SMaximilian Luztriggered by receival of a NAK, means that the packet is added to the queue
2388d779282SMaximilian Luzwith a now incremented number of tries, yielding a higher priority. The
2398d779282SMaximilian Luztimeout for the packet will be disabled until the next transmission attempt
2408d779282SMaximilian Luzand the packet remains on the pending set.
2418d779282SMaximilian Luz
2428d779282SMaximilian LuzNote that due to transmission and packet acknowledgment timeouts, the packet
2438d779282SMaximilian Luztransport layer is always guaranteed to make progress, if only through
2448d779282SMaximilian Luztiming out packets, and will never fully block.
2458d779282SMaximilian Luz
2468d779282SMaximilian LuzConcurrency and Locking
2478d779282SMaximilian Luz-----------------------
2488d779282SMaximilian Luz
2498d779282SMaximilian LuzThere are two main locks in the packet transport layer: One guarding access
2508d779282SMaximilian Luzto the packet queue and one guarding access to the pending set. These
2518d779282SMaximilian Luzcollections may only be accessed and modified under the respective lock. If
2528d779282SMaximilian Luzaccess to both collections is needed, the pending lock must be acquired
2538d779282SMaximilian Luzbefore the queue lock to avoid deadlocks.
2548d779282SMaximilian Luz
2558d779282SMaximilian LuzIn addition to guarding the collections, after initial packet submission
2568d779282SMaximilian Luzcertain packet fields may only be accessed under one of the locks.
2578d779282SMaximilian LuzSpecifically, the packet priority must only be accessed while holding the
2588d779282SMaximilian Luzqueue lock and the packet timestamp must only be accessed while holding the
2598d779282SMaximilian Luzpending lock.
2608d779282SMaximilian Luz
2618d779282SMaximilian LuzOther parts of the packet transport layer are guarded independently. State
2628d779282SMaximilian Luzflags are managed by atomic bit operations and, if necessary, memory
2638d779282SMaximilian Luzbarriers. Modifications to the timeout reaper work item and expiration date
2648d779282SMaximilian Luzare guarded by their own lock.
2658d779282SMaximilian Luz
2668d779282SMaximilian LuzThe reference of the packet to the packet transport layer (``ptl``) is
2678d779282SMaximilian Luzsomewhat special. It is either set when the upper layer request is submitted
2688d779282SMaximilian Luzor, if there is none, when the packet is first submitted. After it is set,
2698d779282SMaximilian Luzit will not change its value. Functions that may run concurrently with
2708d779282SMaximilian Luzsubmission, i.e. cancellation, can not rely on the ``ptl`` reference to be
2718d779282SMaximilian Luzset. Access to it in these functions is guarded by ``READ_ONCE()``, whereas
2728d779282SMaximilian Luzsetting ``ptl`` is equally guarded with ``WRITE_ONCE()`` for symmetry.
2738d779282SMaximilian Luz
2748d779282SMaximilian LuzSome packet fields may be read outside of the respective locks guarding
2758d779282SMaximilian Luzthem, specifically priority and state for tracing. In those cases, proper
2768d779282SMaximilian Luzaccess is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such
2778d779282SMaximilian Luzread-only access is only allowed when stale values are not critical.
2788d779282SMaximilian Luz
2798d779282SMaximilian LuzWith respect to the interface for higher layers, packet submission
2808d779282SMaximilian Luz(|ssh_ptl_submit|), packet cancellation (|ssh_ptl_cancel|), data receival
2818d779282SMaximilian Luz(|ssh_ptl_rx_rcvbuf|), and layer shutdown (|ssh_ptl_shutdown|) may always be
2828d779282SMaximilian Luzexecuted concurrently with respect to each other. Note that packet
2838d779282SMaximilian Luzsubmission may not run concurrently with itself for the same packet.
2848d779282SMaximilian LuzEqually, shutdown and data receival may also not run concurrently with
2858d779282SMaximilian Luzthemselves (but may run concurrently with each other).
2868d779282SMaximilian Luz
2878d779282SMaximilian Luz
2888d779282SMaximilian LuzRequest Transport Layer
2898d779282SMaximilian Luz=======================
2908d779282SMaximilian Luz
2918d779282SMaximilian LuzThe request transport layer is represented via |ssh_rtl| and builds on top
2928d779282SMaximilian Luzof the packet transport layer. It deals with requests, i.e. SSH packets sent
2938d779282SMaximilian Luzby the host containing a |ssh_command| as frame payload. This layer
2948d779282SMaximilian Luzseparates responses to requests from events, which are also sent by the EC
2958d779282SMaximilian Luzvia a |ssh_command| payload. While responses are handled in this layer,
2968d779282SMaximilian Luzevents are relayed to the next upper layer, i.e. the controller layer, via
2978d779282SMaximilian Luzthe corresponding callback. The request transport layer is structured around
2988d779282SMaximilian Luzthe following key concepts:
2998d779282SMaximilian Luz
3008d779282SMaximilian LuzRequest
3018d779282SMaximilian Luz-------
3028d779282SMaximilian Luz
3038d779282SMaximilian LuzRequests are packets with a command-type payload, sent from host to EC to
3048d779282SMaximilian Luzquery data from or trigger an action on it (or both simultaneously). They
3058d779282SMaximilian Luzare represented by |ssh_request|, wrapping the underlying |ssh_packet|
3068d779282SMaximilian Luzstoring its message data (i.e. SSH frame with command payload). Note that
3078d779282SMaximilian Luzall top-level representations, e.g. |ssam_request_sync| are built upon this
3088d779282SMaximilian Luzstruct.
3098d779282SMaximilian Luz
3108d779282SMaximilian LuzAs |ssh_request| extends |ssh_packet|, its lifetime is also managed by the
3118d779282SMaximilian Luzreference counter inside the packet struct (which can be accessed via
3128d779282SMaximilian Luz|ssh_request_get| and |ssh_request_put|). Once the counter reaches zero, the
3138d779282SMaximilian Luz``release()`` callback of the |ssh_request_ops| reference of the request is
3148d779282SMaximilian Luzcalled.
3158d779282SMaximilian Luz
3168d779282SMaximilian LuzRequests can have an optional response that is equally sent via a SSH
3178d779282SMaximilian Luzmessage with command-type payload (from EC to host). The party constructing
3188d779282SMaximilian Luzthe request must know if a response is expected and mark this in the request
3198d779282SMaximilian Luzflags provided to |ssh_request_init|, so that the request transport layer
3208d779282SMaximilian Luzcan wait for this response.
3218d779282SMaximilian Luz
3228d779282SMaximilian LuzSimilar to |ssh_packet|, |ssh_request| also has a ``complete()`` callback
3238d779282SMaximilian Luzprovided via its request ops reference and is guaranteed to be completed
3248d779282SMaximilian Luzbefore it is released once it has been submitted to the request transport
3258d779282SMaximilian Luzlayer via |ssh_rtl_submit|. For a request without a response, successful
3268d779282SMaximilian Luzcompletion will occur once the underlying packet has been successfully
3278d779282SMaximilian Luztransmitted by the packet transport layer (i.e. from within the packet
3288d779282SMaximilian Luzcompletion callback). For a request with response, successful completion
3298d779282SMaximilian Luzwill occur once the response has been received and matched to the request
3308d779282SMaximilian Luzvia its request ID (which happens on the packet layer's data-received
3318d779282SMaximilian Luzcallback running on the receiver thread). If the request is completed with
3328d779282SMaximilian Luzan error, the status value will be set to the corresponding (negative) errno
3338d779282SMaximilian Luzvalue.
3348d779282SMaximilian Luz
3358d779282SMaximilian LuzThe state of a request is again managed via its ``state`` flags
3368d779282SMaximilian Luz(|ssh_request_flags|), which also encode the request type. In particular,
3378d779282SMaximilian Luzthe following bits are noteworthy:
3388d779282SMaximilian Luz
3398d779282SMaximilian Luz* ``SSH_REQUEST_SF_LOCKED_BIT``: This bit is set when completion, either
3408d779282SMaximilian Luz  through error or success, is imminent. It indicates that no further
3418d779282SMaximilian Luz  references of the request should be taken and any existing references
3428d779282SMaximilian Luz  should be dropped as soon as possible. The process setting this bit is
3438d779282SMaximilian Luz  responsible for removing any references to this request from the request
3448d779282SMaximilian Luz  queue and pending set.
3458d779282SMaximilian Luz
3468d779282SMaximilian Luz* ``SSH_REQUEST_SF_COMPLETED_BIT``: This bit is set by the process running the
3478d779282SMaximilian Luz  ``complete()`` callback and is used to ensure that this callback only runs
3488d779282SMaximilian Luz  once.
3498d779282SMaximilian Luz
3508d779282SMaximilian Luz* ``SSH_REQUEST_SF_QUEUED_BIT``: This bit is set when the request is queued on
3518d779282SMaximilian Luz  the request queue and cleared when it is dequeued.
3528d779282SMaximilian Luz
3538d779282SMaximilian Luz* ``SSH_REQUEST_SF_PENDING_BIT``: This bit is set when the request is added to
3548d779282SMaximilian Luz  the pending set and cleared when it is removed from it.
3558d779282SMaximilian Luz
3568d779282SMaximilian LuzRequest Queue
3578d779282SMaximilian Luz-------------
3588d779282SMaximilian Luz
3598d779282SMaximilian LuzThe request queue is the first of the two fundamental collections in the
3608d779282SMaximilian Luzrequest transport layer. In contrast to the packet queue of the packet
3618d779282SMaximilian Luztransport layer, it is not a priority queue and the simple first come first
3628d779282SMaximilian Luzserve principle applies.
3638d779282SMaximilian Luz
3648d779282SMaximilian LuzAll requests to be transmitted by the request transport layer must be
3658d779282SMaximilian Luzsubmitted to this queue via |ssh_rtl_submit|. Once submitted, requests may
3668d779282SMaximilian Luznot be re-submitted, and will not be re-submitted automatically on timeout.
3678d779282SMaximilian LuzInstead, the request is completed with a timeout error. If desired, the
3688d779282SMaximilian Luzcaller can create and submit a new request for another try, but it must not
3698d779282SMaximilian Luzsubmit the same request again.
3708d779282SMaximilian Luz
3718d779282SMaximilian LuzPending Set
3728d779282SMaximilian Luz-----------
3738d779282SMaximilian Luz
3748d779282SMaximilian LuzThe pending set is the second of the two fundamental collections in the
3758d779282SMaximilian Luzrequest transport layer. This collection stores references to all pending
3768d779282SMaximilian Luzrequests, i.e. requests awaiting a response from the EC (similar to what the
3778d779282SMaximilian Luzpending set of the packet transport layer does for packets).
3788d779282SMaximilian Luz
3798d779282SMaximilian LuzTransmitter Task
3808d779282SMaximilian Luz----------------
3818d779282SMaximilian Luz
3828d779282SMaximilian LuzThe transmitter task is scheduled when a new request is available for
3838d779282SMaximilian Luztransmission. It checks if the next request on the request queue can be
3848d779282SMaximilian Luztransmitted and, if so, submits its underlying packet to the packet
3858d779282SMaximilian Luztransport layer. This check ensures that only a limited number of
3868d779282SMaximilian Luzrequests can be pending, i.e. waiting for a response, at the same time. If
3878d779282SMaximilian Luzthe request requires a response, the request is added to the pending set
3888d779282SMaximilian Luzbefore its packet is submitted.
3898d779282SMaximilian Luz
3908d779282SMaximilian LuzPacket Completion Callback
3918d779282SMaximilian Luz--------------------------
3928d779282SMaximilian Luz
3938d779282SMaximilian LuzThe packet completion callback is executed once the underlying packet of a
3948d779282SMaximilian Luzrequest has been completed. In case of an error completion, the
3958d779282SMaximilian Luzcorresponding request is completed with the error value provided in this
3968d779282SMaximilian Luzcallback.
3978d779282SMaximilian Luz
3988d779282SMaximilian LuzOn successful packet completion, further processing depends on the request.
3998d779282SMaximilian LuzIf the request expects a response, it is marked as transmitted and the
4008d779282SMaximilian Luzrequest timeout is started. If the request does not expect a response, it is
4018d779282SMaximilian Luzcompleted with success.
4028d779282SMaximilian Luz
4038d779282SMaximilian LuzData-Received Callback
4048d779282SMaximilian Luz----------------------
4058d779282SMaximilian Luz
4068d779282SMaximilian LuzThe data received callback notifies the request transport layer of data
4078d779282SMaximilian Luzbeing received by the underlying packet transport layer via a data-type
4088d779282SMaximilian Luzframe. In general, this is expected to be a command-type payload.
4098d779282SMaximilian Luz
4108d779282SMaximilian LuzIf the request ID of the command is one of the request IDs reserved for
4118d779282SMaximilian Luzevents (one to ``SSH_NUM_EVENTS``, inclusively), it is forwarded to the
4128d779282SMaximilian Luzevent callback registered in the request transport layer. If the request ID
4138d779282SMaximilian Luzindicates a response to a request, the respective request is looked up in
4148d779282SMaximilian Luzthe pending set and, if found and marked as transmitted, completed with
4158d779282SMaximilian Luzsuccess.
4168d779282SMaximilian Luz
4178d779282SMaximilian LuzTimeout Reaper
4188d779282SMaximilian Luz--------------
4198d779282SMaximilian Luz
4208d779282SMaximilian LuzThe request-response-timeout is a per-request timeout for requests expecting
4218d779282SMaximilian Luza response. It is used to ensure that a request does not wait indefinitely
4228d779282SMaximilian Luzon a response from the EC and is started after the underlying packet has
4238d779282SMaximilian Luzbeen successfully completed.
4248d779282SMaximilian Luz
4258d779282SMaximilian LuzThis timeout is, similar to the packet acknowledgment timeout on the packet
4268d779282SMaximilian Luztransport layer, handled via a dedicated reaper task. This task is
4278d779282SMaximilian Luzessentially a work-item (re-)scheduled to run when the next request is set
4288d779282SMaximilian Luzto time out. The work item then scans the set of pending requests for any
4298d779282SMaximilian Luzrequests that have timed out and completes them with ``-ETIMEDOUT`` as
4308d779282SMaximilian Luzstatus. Requests will not be re-submitted automatically. Instead, the issuer
4318d779282SMaximilian Luzof the request must construct and submit a new request, if so desired.
4328d779282SMaximilian Luz
4338d779282SMaximilian LuzNote that this timeout, in combination with packet transmission and
4348d779282SMaximilian Luzacknowledgment timeouts, guarantees that the request layer will always make
4358d779282SMaximilian Luzprogress, even if only through timing out packets, and never fully block.
4368d779282SMaximilian Luz
4378d779282SMaximilian LuzConcurrency and Locking
4388d779282SMaximilian Luz-----------------------
4398d779282SMaximilian Luz
4408d779282SMaximilian LuzSimilar to the packet transport layer, there are two main locks in the
4418d779282SMaximilian Luzrequest transport layer: One guarding access to the request queue and one
4428d779282SMaximilian Luzguarding access to the pending set. These collections may only be accessed
4438d779282SMaximilian Luzand modified under the respective lock.
4448d779282SMaximilian Luz
4458d779282SMaximilian LuzOther parts of the request transport layer are guarded independently. State
4468d779282SMaximilian Luzflags are (again) managed by atomic bit operations and, if necessary, memory
4478d779282SMaximilian Luzbarriers. Modifications to the timeout reaper work item and expiration date
4488d779282SMaximilian Luzare guarded by their own lock.
4498d779282SMaximilian Luz
4508d779282SMaximilian LuzSome request fields may be read outside of the respective locks guarding
4518d779282SMaximilian Luzthem, specifically the state for tracing. In those cases, proper access is
4528d779282SMaximilian Luzensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such read-only
4538d779282SMaximilian Luzaccess is only allowed when stale values are not critical.
4548d779282SMaximilian Luz
4558d779282SMaximilian LuzWith respect to the interface for higher layers, request submission
4568d779282SMaximilian Luz(|ssh_rtl_submit|), request cancellation (|ssh_rtl_cancel|), and layer
4578d779282SMaximilian Luzshutdown (|ssh_rtl_shutdown|) may always be executed concurrently with
4588d779282SMaximilian Luzrespect to each other. Note that request submission may not run concurrently
4598d779282SMaximilian Luzwith itself for the same request (and also may only be called once per
4608d779282SMaximilian Luzrequest). Equally, shutdown may also not run concurrently with itself.
4618d779282SMaximilian Luz
4628d779282SMaximilian Luz
4638d779282SMaximilian LuzController Layer
4648d779282SMaximilian Luz================
4658d779282SMaximilian Luz
4668d779282SMaximilian LuzThe controller layer extends on the request transport layer to provide an
4678d779282SMaximilian Luzeasy-to-use interface for client drivers. It is represented by
4688d779282SMaximilian Luz|ssam_controller| and the SSH driver. While the lower level transport layers
4698d779282SMaximilian Luztake care of transmitting and handling packets and requests, the controller
4708d779282SMaximilian Luzlayer takes on more of a management role. Specifically, it handles device
4718d779282SMaximilian Luzinitialization, power management, and event handling, including event
4728d779282SMaximilian Luzdelivery and registration via the (event) completion system (|ssam_cplt|).
4738d779282SMaximilian Luz
4748d779282SMaximilian LuzEvent Registration
4758d779282SMaximilian Luz------------------
4768d779282SMaximilian Luz
4778d779282SMaximilian LuzIn general, an event (or rather a class of events) has to be explicitly
4788d779282SMaximilian Luzrequested by the host before the EC will send it (HID input events seem to
4798d779282SMaximilian Luzbe the exception). This is done via an event-enable request (similarly,
4808d779282SMaximilian Luzevents should be disabled via an event-disable request once no longer
4818d779282SMaximilian Luzdesired).
4828d779282SMaximilian Luz
4838d779282SMaximilian LuzThe specific request used to enable (or disable) an event is given via an
4848d779282SMaximilian Luzevent registry, i.e. the governing authority of this event (so to speak),
4858d779282SMaximilian Luzrepresented by |ssam_event_registry|. As parameters to this request, the
4868d779282SMaximilian Luztarget category and, depending on the event registry, instance ID of the
4878d779282SMaximilian Luzevent to be enabled must be provided. This (optional) instance ID must be
4888d779282SMaximilian Luzzero if the registry does not use it. Together, target category and instance
4898d779282SMaximilian LuzID form the event ID, represented by |ssam_event_id|. In short, both, event
4908d779282SMaximilian Luzregistry and event ID, are required to uniquely identify a respective class
4918d779282SMaximilian Luzof events.
4928d779282SMaximilian Luz
4938d779282SMaximilian LuzNote that a further *request ID* parameter must be provided for the
4948d779282SMaximilian Luzenable-event request. This parameter does not influence the class of events
4958d779282SMaximilian Luzbeing enabled, but instead is set as the request ID (RQID) on each event of
4968d779282SMaximilian Luzthis class sent by the EC. It is used to identify events (as a limited
4978d779282SMaximilian Luznumber of request IDs is reserved for use in events only, specifically one
4988d779282SMaximilian Luzto ``SSH_NUM_EVENTS`` inclusively) and also map events to their specific
4998d779282SMaximilian Luzclass. Currently, the controller always sets this parameter to the target
5008d779282SMaximilian Luzcategory specified in |ssam_event_id|.
5018d779282SMaximilian Luz
5028d779282SMaximilian LuzAs multiple client drivers may rely on the same (or overlapping) classes of
5038d779282SMaximilian Luzevents and enable/disable calls are strictly binary (i.e. on/off), the
5048d779282SMaximilian Luzcontroller has to manage access to these events. It does so via reference
5058d779282SMaximilian Luzcounting, storing the counter inside an RB-tree based mapping with event
5068d779282SMaximilian Luzregistry and ID as key (there is no known list of valid event registry and
5078d779282SMaximilian Luzevent ID combinations). See |ssam_nf|, |ssam_nf_refcount_inc|, and
5088d779282SMaximilian Luz|ssam_nf_refcount_dec| for details.
5098d779282SMaximilian Luz
5108d779282SMaximilian LuzThis management is done together with notifier registration (described in
5118d779282SMaximilian Luzthe next section) via the top-level |ssam_notifier_register| and
5128d779282SMaximilian Luz|ssam_notifier_unregister| functions.
5138d779282SMaximilian Luz
5148d779282SMaximilian LuzEvent Delivery
5158d779282SMaximilian Luz--------------
5168d779282SMaximilian Luz
5178d779282SMaximilian LuzTo receive events, a client driver has to register an event notifier via
5188d779282SMaximilian Luz|ssam_notifier_register|. This increments the reference counter for that
5198d779282SMaximilian Luzspecific class of events (as detailed in the previous section), enables the
5208d779282SMaximilian Luzclass on the EC (if it has not been enabled already), and installs the
5218d779282SMaximilian Luzprovided notifier callback.
5228d779282SMaximilian Luz
5238d779282SMaximilian LuzNotifier callbacks are stored in lists, with one (RCU) list per target
5248d779282SMaximilian Luzcategory (provided via the event ID; NB: there is a fixed known number of
5258d779282SMaximilian Luztarget categories). There is no known association from the combination of
5268d779282SMaximilian Luzevent registry and event ID to the command data (target ID, target category,
5278d779282SMaximilian Luzcommand ID, and instance ID) that can be provided by an event class, apart
5288d779282SMaximilian Luzfrom target category and instance ID given via the event ID.
5298d779282SMaximilian Luz
5308d779282SMaximilian LuzNote that due to the way notifiers are (or rather have to be) stored, client
5318d779282SMaximilian Luzdrivers may receive events that they have not requested and need to account
5328d779282SMaximilian Luzfor them. Specifically, they will, by default, receive all events from the
5338d779282SMaximilian Luzsame target category. To simplify dealing with this, filtering of events by
5348d779282SMaximilian Luztarget ID (provided via the event registry) and instance ID (provided via
5358d779282SMaximilian Luzthe event ID) can be requested when registering a notifier. This filtering
5368d779282SMaximilian Luzis applied when iterating over the notifiers at the time they are executed.
5378d779282SMaximilian Luz
5388d779282SMaximilian LuzAll notifier callbacks are executed on a dedicated workqueue, the so-called
5398d779282SMaximilian Luzcompletion workqueue. After an event has been received via the callback
5408d779282SMaximilian Luzinstalled in the request layer (running on the receiver thread of the packet
5418d779282SMaximilian Luztransport layer), it will be put on its respective event queue
5428d779282SMaximilian Luz(|ssam_event_queue|). From this event queue the completion work item of that
5438d779282SMaximilian Luzqueue (running on the completion workqueue) will pick up the event and
5448d779282SMaximilian Luzexecute the notifier callback. This is done to avoid blocking on the
5458d779282SMaximilian Luzreceiver thread.
5468d779282SMaximilian Luz
5478d779282SMaximilian LuzThere is one event queue per combination of target ID and target category.
5488d779282SMaximilian LuzThis is done to ensure that notifier callbacks are executed in sequence for
5498d779282SMaximilian Luzevents of the same target ID and target category. Callbacks can be executed
5508d779282SMaximilian Luzin parallel for events with a different combination of target ID and target
5518d779282SMaximilian Luzcategory.
5528d779282SMaximilian Luz
5538d779282SMaximilian LuzConcurrency and Locking
5548d779282SMaximilian Luz-----------------------
5558d779282SMaximilian Luz
5568d779282SMaximilian LuzMost of the concurrency related safety guarantees of the controller are
5578d779282SMaximilian Luzprovided by the lower-level request transport layer. In addition to this,
5588d779282SMaximilian Luzevent (un-)registration is guarded by its own lock.
5598d779282SMaximilian Luz
5608d779282SMaximilian LuzAccess to the controller state is guarded by the state lock. This lock is a
5618d779282SMaximilian Luzread/write semaphore. The reader part can be used to ensure that the state
5628d779282SMaximilian Luzdoes not change while functions depending on the state to stay the same
5638d779282SMaximilian Luz(e.g. |ssam_notifier_register|, |ssam_notifier_unregister|,
5648d779282SMaximilian Luz|ssam_request_sync_submit|, and derivatives) are executed and this guarantee
5658d779282SMaximilian Luzis not already provided otherwise (e.g. through |ssam_client_bind| or
5668d779282SMaximilian Luz|ssam_client_link|). The writer part guards any transitions that will change
5678d779282SMaximilian Luzthe state, i.e. initialization, destruction, suspension, and resumption.
5688d779282SMaximilian Luz
5698d779282SMaximilian LuzThe controller state may be accessed (read-only) outside the state lock for
5708d779282SMaximilian Luzsmoke-testing against invalid API usage (e.g. in |ssam_request_sync_submit|).
5718d779282SMaximilian LuzNote that such checks are not supposed to (and will not) protect against all
5728d779282SMaximilian Luzinvalid usages, but rather aim to help catch them. In those cases, proper
5738d779282SMaximilian Luzvariable access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``.
5748d779282SMaximilian Luz
5758d779282SMaximilian LuzAssuming any preconditions on the state not changing have been satisfied,
5768d779282SMaximilian Luzall non-initialization and non-shutdown functions may run concurrently with
5778d779282SMaximilian Luzeach other. This includes |ssam_notifier_register|, |ssam_notifier_unregister|,
5788d779282SMaximilian Luz|ssam_request_sync_submit|, as well as all functions building on top of those.
579