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