0001 .. SPDX-License-Identifier: GPL-2.0+
0002
0003 .. |ssh_ptl| replace:: :c:type:`struct ssh_ptl <ssh_ptl>`
0004 .. |ssh_ptl_submit| replace:: :c:func:`ssh_ptl_submit`
0005 .. |ssh_ptl_cancel| replace:: :c:func:`ssh_ptl_cancel`
0006 .. |ssh_ptl_shutdown| replace:: :c:func:`ssh_ptl_shutdown`
0007 .. |ssh_ptl_rx_rcvbuf| replace:: :c:func:`ssh_ptl_rx_rcvbuf`
0008 .. |ssh_rtl| replace:: :c:type:`struct ssh_rtl <ssh_rtl>`
0009 .. |ssh_rtl_submit| replace:: :c:func:`ssh_rtl_submit`
0010 .. |ssh_rtl_cancel| replace:: :c:func:`ssh_rtl_cancel`
0011 .. |ssh_rtl_shutdown| replace:: :c:func:`ssh_rtl_shutdown`
0012 .. |ssh_packet| replace:: :c:type:`struct ssh_packet <ssh_packet>`
0013 .. |ssh_packet_get| replace:: :c:func:`ssh_packet_get`
0014 .. |ssh_packet_put| replace:: :c:func:`ssh_packet_put`
0015 .. |ssh_packet_ops| replace:: :c:type:`struct ssh_packet_ops <ssh_packet_ops>`
0016 .. |ssh_packet_base_priority| replace:: :c:type:`enum ssh_packet_base_priority <ssh_packet_base_priority>`
0017 .. |ssh_packet_flags| replace:: :c:type:`enum ssh_packet_flags <ssh_packet_flags>`
0018 .. |SSH_PACKET_PRIORITY| replace:: :c:func:`SSH_PACKET_PRIORITY`
0019 .. |ssh_frame| replace:: :c:type:`struct ssh_frame <ssh_frame>`
0020 .. |ssh_command| replace:: :c:type:`struct ssh_command <ssh_command>`
0021 .. |ssh_request| replace:: :c:type:`struct ssh_request <ssh_request>`
0022 .. |ssh_request_get| replace:: :c:func:`ssh_request_get`
0023 .. |ssh_request_put| replace:: :c:func:`ssh_request_put`
0024 .. |ssh_request_ops| replace:: :c:type:`struct ssh_request_ops <ssh_request_ops>`
0025 .. |ssh_request_init| replace:: :c:func:`ssh_request_init`
0026 .. |ssh_request_flags| replace:: :c:type:`enum ssh_request_flags <ssh_request_flags>`
0027 .. |ssam_controller| replace:: :c:type:`struct ssam_controller <ssam_controller>`
0028 .. |ssam_device| replace:: :c:type:`struct ssam_device <ssam_device>`
0029 .. |ssam_device_driver| replace:: :c:type:`struct ssam_device_driver <ssam_device_driver>`
0030 .. |ssam_client_bind| replace:: :c:func:`ssam_client_bind`
0031 .. |ssam_client_link| replace:: :c:func:`ssam_client_link`
0032 .. |ssam_request_sync| replace:: :c:type:`struct ssam_request_sync <ssam_request_sync>`
0033 .. |ssam_event_registry| replace:: :c:type:`struct ssam_event_registry <ssam_event_registry>`
0034 .. |ssam_event_id| replace:: :c:type:`struct ssam_event_id <ssam_event_id>`
0035 .. |ssam_nf| replace:: :c:type:`struct ssam_nf <ssam_nf>`
0036 .. |ssam_nf_refcount_inc| replace:: :c:func:`ssam_nf_refcount_inc`
0037 .. |ssam_nf_refcount_dec| replace:: :c:func:`ssam_nf_refcount_dec`
0038 .. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register`
0039 .. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister`
0040 .. |ssam_cplt| replace:: :c:type:`struct ssam_cplt <ssam_cplt>`
0041 .. |ssam_event_queue| replace:: :c:type:`struct ssam_event_queue <ssam_event_queue>`
0042 .. |ssam_request_sync_submit| replace:: :c:func:`ssam_request_sync_submit`
0043
0044 =====================
0045 Core Driver Internals
0046 =====================
0047
0048 Architectural overview of the Surface System Aggregator Module (SSAM) core
0049 and Surface Serial Hub (SSH) driver. For the API documentation, refer to:
0050
0051 .. toctree::
0052 :maxdepth: 2
0053
0054 internal-api
0055
0056
0057 Overview
0058 ========
0059
0060 The SSAM core implementation is structured in layers, somewhat following the
0061 SSH protocol structure:
0062
0063 Lower-level packet transport is implemented in the *packet transport layer
0064 (PTL)*, directly building on top of the serial device (serdev)
0065 infrastructure of the kernel. As the name indicates, this layer deals with
0066 the packet transport logic and handles things like packet validation, packet
0067 acknowledgment (ACKing), packet (retransmission) timeouts, and relaying
0068 packet payloads to higher-level layers.
0069
0070 Above this sits the *request transport layer (RTL)*. This layer is centered
0071 around command-type packet payloads, i.e. requests (sent from host to EC),
0072 responses of the EC to those requests, and events (sent from EC to host).
0073 It, specifically, distinguishes events from request responses, matches
0074 responses to their corresponding requests, and implements request timeouts.
0075
0076 The *controller* layer is building on top of this and essentially decides
0077 how request responses and, especially, events are dealt with. It provides an
0078 event notifier system, handles event activation/deactivation, provides a
0079 workqueue for event and asynchronous request completion, and also manages
0080 the message counters required for building command messages (``SEQ``,
0081 ``RQID``). This layer basically provides a fundamental interface to the SAM
0082 EC for use in other kernel drivers.
0083
0084 While the controller layer already provides an interface for other kernel
0085 drivers, the client *bus* extends this interface to provide support for
0086 native SSAM devices, i.e. devices that are not defined in ACPI and not
0087 implemented as platform devices, via |ssam_device| and |ssam_device_driver|
0088 simplify management of client devices and client drivers.
0089
0090 Refer to Documentation/driver-api/surface_aggregator/client.rst for
0091 documentation regarding the client device/driver API and interface options
0092 for other kernel drivers. It is recommended to familiarize oneself with
0093 that chapter and the Documentation/driver-api/surface_aggregator/ssh.rst
0094 before continuing with the architectural overview below.
0095
0096
0097 Packet Transport Layer
0098 ======================
0099
0100 The packet transport layer is represented via |ssh_ptl| and is structured
0101 around the following key concepts:
0102
0103 Packets
0104 -------
0105
0106 Packets are the fundamental transmission unit of the SSH protocol. They are
0107 managed by the packet transport layer, which is essentially the lowest layer
0108 of the driver and is built upon by other components of the SSAM core.
0109 Packets to be transmitted by the SSAM core are represented via |ssh_packet|
0110 (in contrast, packets received by the core do not have any specific
0111 structure and are managed entirely via the raw |ssh_frame|).
0112
0113 This structure contains the required fields to manage the packet inside the
0114 transport layer, as well as a reference to the buffer containing the data to
0115 be transmitted (i.e. the message wrapped in |ssh_frame|). Most notably, it
0116 contains an internal reference count, which is used for managing its
0117 lifetime (accessible via |ssh_packet_get| and |ssh_packet_put|). When this
0118 counter reaches zero, the ``release()`` callback provided to the packet via
0119 its |ssh_packet_ops| reference is executed, which may then deallocate the
0120 packet or its enclosing structure (e.g. |ssh_request|).
0121
0122 In addition to the ``release`` callback, the |ssh_packet_ops| reference also
0123 provides a ``complete()`` callback, which is run once the packet has been
0124 completed and provides the status of this completion, i.e. zero on success
0125 or a negative errno value in case of an error. Once the packet has been
0126 submitted to the packet transport layer, the ``complete()`` callback is
0127 always guaranteed to be executed before the ``release()`` callback, i.e. the
0128 packet will always be completed, either successfully, with an error, or due
0129 to cancellation, before it will be released.
0130
0131 The state of a packet is managed via its ``state`` flags
0132 (|ssh_packet_flags|), which also contains the packet type. In particular,
0133 the following bits are noteworthy:
0134
0135 * ``SSH_PACKET_SF_LOCKED_BIT``: This bit is set when completion, either
0136 through error or success, is imminent. It indicates that no further
0137 references of the packet should be taken and any existing references
0138 should be dropped as soon as possible. The process setting this bit is
0139 responsible for removing any references to this packet from the packet
0140 queue and pending set.
0141
0142 * ``SSH_PACKET_SF_COMPLETED_BIT``: This bit is set by the process running the
0143 ``complete()`` callback and is used to ensure that this callback only runs
0144 once.
0145
0146 * ``SSH_PACKET_SF_QUEUED_BIT``: This bit is set when the packet is queued on
0147 the packet queue and cleared when it is dequeued.
0148
0149 * ``SSH_PACKET_SF_PENDING_BIT``: This bit is set when the packet is added to
0150 the pending set and cleared when it is removed from it.
0151
0152 Packet Queue
0153 ------------
0154
0155 The packet queue is the first of the two fundamental collections in the
0156 packet transport layer. It is a priority queue, with priority of the
0157 respective packets based on the packet type (major) and number of tries
0158 (minor). See |SSH_PACKET_PRIORITY| for more details on the priority value.
0159
0160 All packets to be transmitted by the transport layer must be submitted to
0161 this queue via |ssh_ptl_submit|. Note that this includes control packets
0162 sent by the transport layer itself. Internally, data packets can be
0163 re-submitted to this queue due to timeouts or NAK packets sent by the EC.
0164
0165 Pending Set
0166 -----------
0167
0168 The pending set is the second of the two fundamental collections in the
0169 packet transport layer. It stores references to packets that have already
0170 been transmitted, but wait for acknowledgment (e.g. the corresponding ACK
0171 packet) by the EC.
0172
0173 Note that a packet may both be pending and queued if it has been
0174 re-submitted due to a packet acknowledgment timeout or NAK. On such a
0175 re-submission, packets are not removed from the pending set.
0176
0177 Transmitter Thread
0178 ------------------
0179
0180 The transmitter thread is responsible for most of the actual work regarding
0181 packet transmission. In each iteration, it (waits for and) checks if the
0182 next packet on the queue (if any) can be transmitted and, if so, removes it
0183 from the queue and increments its counter for the number of transmission
0184 attempts, i.e. tries. If the packet is sequenced, i.e. requires an ACK by
0185 the EC, the packet is added to the pending set. Next, the packet's data is
0186 submitted to the serdev subsystem. In case of an error or timeout during
0187 this submission, the packet is completed by the transmitter thread with the
0188 status value of the callback set accordingly. In case the packet is
0189 unsequenced, i.e. does not require an ACK by the EC, the packet is completed
0190 with success on the transmitter thread.
0191
0192 Transmission of sequenced packets is limited by the number of concurrently
0193 pending packets, i.e. a limit on how many packets may be waiting for an ACK
0194 from the EC in parallel. This limit is currently set to one (see
0195 Documentation/driver-api/surface_aggregator/ssh.rst for the reasoning behind
0196 this). Control packets (i.e. ACK and NAK) can always be transmitted.
0197
0198 Receiver Thread
0199 ---------------
0200
0201 Any data received from the EC is put into a FIFO buffer for further
0202 processing. This processing happens on the receiver thread. The receiver
0203 thread parses and validates the received message into its |ssh_frame| and
0204 corresponding payload. It prepares and submits the necessary ACK (and on
0205 validation error or invalid data NAK) packets for the received messages.
0206
0207 This thread also handles further processing, such as matching ACK messages
0208 to the corresponding pending packet (via sequence ID) and completing it, as
0209 well as initiating re-submission of all currently pending packets on
0210 receival of a NAK message (re-submission in case of a NAK is similar to
0211 re-submission due to timeout, see below for more details on that). Note that
0212 the successful completion of a sequenced packet will always run on the
0213 receiver thread (whereas any failure-indicating completion will run on the
0214 process where the failure occurred).
0215
0216 Any payload data is forwarded via a callback to the next upper layer, i.e.
0217 the request transport layer.
0218
0219 Timeout Reaper
0220 --------------
0221
0222 The packet acknowledgment timeout is a per-packet timeout for sequenced
0223 packets, started when the respective packet begins (re-)transmission (i.e.
0224 this timeout is armed once per transmission attempt on the transmitter
0225 thread). It is used to trigger re-submission or, when the number of tries
0226 has been exceeded, cancellation of the packet in question.
0227
0228 This timeout is handled via a dedicated reaper task, which is essentially a
0229 work item (re-)scheduled to run when the next packet is set to time out. The
0230 work item then checks the set of pending packets for any packets that have
0231 exceeded the timeout and, if there are any remaining packets, re-schedules
0232 itself to the next appropriate point in time.
0233
0234 If a timeout has been detected by the reaper, the packet will either be
0235 re-submitted if it still has some remaining tries left, or completed with
0236 ``-ETIMEDOUT`` as status if not. Note that re-submission, in this case and
0237 triggered by receival of a NAK, means that the packet is added to the queue
0238 with a now incremented number of tries, yielding a higher priority. The
0239 timeout for the packet will be disabled until the next transmission attempt
0240 and the packet remains on the pending set.
0241
0242 Note that due to transmission and packet acknowledgment timeouts, the packet
0243 transport layer is always guaranteed to make progress, if only through
0244 timing out packets, and will never fully block.
0245
0246 Concurrency and Locking
0247 -----------------------
0248
0249 There are two main locks in the packet transport layer: One guarding access
0250 to the packet queue and one guarding access to the pending set. These
0251 collections may only be accessed and modified under the respective lock. If
0252 access to both collections is needed, the pending lock must be acquired
0253 before the queue lock to avoid deadlocks.
0254
0255 In addition to guarding the collections, after initial packet submission
0256 certain packet fields may only be accessed under one of the locks.
0257 Specifically, the packet priority must only be accessed while holding the
0258 queue lock and the packet timestamp must only be accessed while holding the
0259 pending lock.
0260
0261 Other parts of the packet transport layer are guarded independently. State
0262 flags are managed by atomic bit operations and, if necessary, memory
0263 barriers. Modifications to the timeout reaper work item and expiration date
0264 are guarded by their own lock.
0265
0266 The reference of the packet to the packet transport layer (``ptl``) is
0267 somewhat special. It is either set when the upper layer request is submitted
0268 or, if there is none, when the packet is first submitted. After it is set,
0269 it will not change its value. Functions that may run concurrently with
0270 submission, i.e. cancellation, can not rely on the ``ptl`` reference to be
0271 set. Access to it in these functions is guarded by ``READ_ONCE()``, whereas
0272 setting ``ptl`` is equally guarded with ``WRITE_ONCE()`` for symmetry.
0273
0274 Some packet fields may be read outside of the respective locks guarding
0275 them, specifically priority and state for tracing. In those cases, proper
0276 access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such
0277 read-only access is only allowed when stale values are not critical.
0278
0279 With respect to the interface for higher layers, packet submission
0280 (|ssh_ptl_submit|), packet cancellation (|ssh_ptl_cancel|), data receival
0281 (|ssh_ptl_rx_rcvbuf|), and layer shutdown (|ssh_ptl_shutdown|) may always be
0282 executed concurrently with respect to each other. Note that packet
0283 submission may not run concurrently with itself for the same packet.
0284 Equally, shutdown and data receival may also not run concurrently with
0285 themselves (but may run concurrently with each other).
0286
0287
0288 Request Transport Layer
0289 =======================
0290
0291 The request transport layer is represented via |ssh_rtl| and builds on top
0292 of the packet transport layer. It deals with requests, i.e. SSH packets sent
0293 by the host containing a |ssh_command| as frame payload. This layer
0294 separates responses to requests from events, which are also sent by the EC
0295 via a |ssh_command| payload. While responses are handled in this layer,
0296 events are relayed to the next upper layer, i.e. the controller layer, via
0297 the corresponding callback. The request transport layer is structured around
0298 the following key concepts:
0299
0300 Request
0301 -------
0302
0303 Requests are packets with a command-type payload, sent from host to EC to
0304 query data from or trigger an action on it (or both simultaneously). They
0305 are represented by |ssh_request|, wrapping the underlying |ssh_packet|
0306 storing its message data (i.e. SSH frame with command payload). Note that
0307 all top-level representations, e.g. |ssam_request_sync| are built upon this
0308 struct.
0309
0310 As |ssh_request| extends |ssh_packet|, its lifetime is also managed by the
0311 reference counter inside the packet struct (which can be accessed via
0312 |ssh_request_get| and |ssh_request_put|). Once the counter reaches zero, the
0313 ``release()`` callback of the |ssh_request_ops| reference of the request is
0314 called.
0315
0316 Requests can have an optional response that is equally sent via a SSH
0317 message with command-type payload (from EC to host). The party constructing
0318 the request must know if a response is expected and mark this in the request
0319 flags provided to |ssh_request_init|, so that the request transport layer
0320 can wait for this response.
0321
0322 Similar to |ssh_packet|, |ssh_request| also has a ``complete()`` callback
0323 provided via its request ops reference and is guaranteed to be completed
0324 before it is released once it has been submitted to the request transport
0325 layer via |ssh_rtl_submit|. For a request without a response, successful
0326 completion will occur once the underlying packet has been successfully
0327 transmitted by the packet transport layer (i.e. from within the packet
0328 completion callback). For a request with response, successful completion
0329 will occur once the response has been received and matched to the request
0330 via its request ID (which happens on the packet layer's data-received
0331 callback running on the receiver thread). If the request is completed with
0332 an error, the status value will be set to the corresponding (negative) errno
0333 value.
0334
0335 The state of a request is again managed via its ``state`` flags
0336 (|ssh_request_flags|), which also encode the request type. In particular,
0337 the following bits are noteworthy:
0338
0339 * ``SSH_REQUEST_SF_LOCKED_BIT``: This bit is set when completion, either
0340 through error or success, is imminent. It indicates that no further
0341 references of the request should be taken and any existing references
0342 should be dropped as soon as possible. The process setting this bit is
0343 responsible for removing any references to this request from the request
0344 queue and pending set.
0345
0346 * ``SSH_REQUEST_SF_COMPLETED_BIT``: This bit is set by the process running the
0347 ``complete()`` callback and is used to ensure that this callback only runs
0348 once.
0349
0350 * ``SSH_REQUEST_SF_QUEUED_BIT``: This bit is set when the request is queued on
0351 the request queue and cleared when it is dequeued.
0352
0353 * ``SSH_REQUEST_SF_PENDING_BIT``: This bit is set when the request is added to
0354 the pending set and cleared when it is removed from it.
0355
0356 Request Queue
0357 -------------
0358
0359 The request queue is the first of the two fundamental collections in the
0360 request transport layer. In contrast to the packet queue of the packet
0361 transport layer, it is not a priority queue and the simple first come first
0362 serve principle applies.
0363
0364 All requests to be transmitted by the request transport layer must be
0365 submitted to this queue via |ssh_rtl_submit|. Once submitted, requests may
0366 not be re-submitted, and will not be re-submitted automatically on timeout.
0367 Instead, the request is completed with a timeout error. If desired, the
0368 caller can create and submit a new request for another try, but it must not
0369 submit the same request again.
0370
0371 Pending Set
0372 -----------
0373
0374 The pending set is the second of the two fundamental collections in the
0375 request transport layer. This collection stores references to all pending
0376 requests, i.e. requests awaiting a response from the EC (similar to what the
0377 pending set of the packet transport layer does for packets).
0378
0379 Transmitter Task
0380 ----------------
0381
0382 The transmitter task is scheduled when a new request is available for
0383 transmission. It checks if the next request on the request queue can be
0384 transmitted and, if so, submits its underlying packet to the packet
0385 transport layer. This check ensures that only a limited number of
0386 requests can be pending, i.e. waiting for a response, at the same time. If
0387 the request requires a response, the request is added to the pending set
0388 before its packet is submitted.
0389
0390 Packet Completion Callback
0391 --------------------------
0392
0393 The packet completion callback is executed once the underlying packet of a
0394 request has been completed. In case of an error completion, the
0395 corresponding request is completed with the error value provided in this
0396 callback.
0397
0398 On successful packet completion, further processing depends on the request.
0399 If the request expects a response, it is marked as transmitted and the
0400 request timeout is started. If the request does not expect a response, it is
0401 completed with success.
0402
0403 Data-Received Callback
0404 ----------------------
0405
0406 The data received callback notifies the request transport layer of data
0407 being received by the underlying packet transport layer via a data-type
0408 frame. In general, this is expected to be a command-type payload.
0409
0410 If the request ID of the command is one of the request IDs reserved for
0411 events (one to ``SSH_NUM_EVENTS``, inclusively), it is forwarded to the
0412 event callback registered in the request transport layer. If the request ID
0413 indicates a response to a request, the respective request is looked up in
0414 the pending set and, if found and marked as transmitted, completed with
0415 success.
0416
0417 Timeout Reaper
0418 --------------
0419
0420 The request-response-timeout is a per-request timeout for requests expecting
0421 a response. It is used to ensure that a request does not wait indefinitely
0422 on a response from the EC and is started after the underlying packet has
0423 been successfully completed.
0424
0425 This timeout is, similar to the packet acknowledgment timeout on the packet
0426 transport layer, handled via a dedicated reaper task. This task is
0427 essentially a work-item (re-)scheduled to run when the next request is set
0428 to time out. The work item then scans the set of pending requests for any
0429 requests that have timed out and completes them with ``-ETIMEDOUT`` as
0430 status. Requests will not be re-submitted automatically. Instead, the issuer
0431 of the request must construct and submit a new request, if so desired.
0432
0433 Note that this timeout, in combination with packet transmission and
0434 acknowledgment timeouts, guarantees that the request layer will always make
0435 progress, even if only through timing out packets, and never fully block.
0436
0437 Concurrency and Locking
0438 -----------------------
0439
0440 Similar to the packet transport layer, there are two main locks in the
0441 request transport layer: One guarding access to the request queue and one
0442 guarding access to the pending set. These collections may only be accessed
0443 and modified under the respective lock.
0444
0445 Other parts of the request transport layer are guarded independently. State
0446 flags are (again) managed by atomic bit operations and, if necessary, memory
0447 barriers. Modifications to the timeout reaper work item and expiration date
0448 are guarded by their own lock.
0449
0450 Some request fields may be read outside of the respective locks guarding
0451 them, specifically the state for tracing. In those cases, proper access is
0452 ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such read-only
0453 access is only allowed when stale values are not critical.
0454
0455 With respect to the interface for higher layers, request submission
0456 (|ssh_rtl_submit|), request cancellation (|ssh_rtl_cancel|), and layer
0457 shutdown (|ssh_rtl_shutdown|) may always be executed concurrently with
0458 respect to each other. Note that request submission may not run concurrently
0459 with itself for the same request (and also may only be called once per
0460 request). Equally, shutdown may also not run concurrently with itself.
0461
0462
0463 Controller Layer
0464 ================
0465
0466 The controller layer extends on the request transport layer to provide an
0467 easy-to-use interface for client drivers. It is represented by
0468 |ssam_controller| and the SSH driver. While the lower level transport layers
0469 take care of transmitting and handling packets and requests, the controller
0470 layer takes on more of a management role. Specifically, it handles device
0471 initialization, power management, and event handling, including event
0472 delivery and registration via the (event) completion system (|ssam_cplt|).
0473
0474 Event Registration
0475 ------------------
0476
0477 In general, an event (or rather a class of events) has to be explicitly
0478 requested by the host before the EC will send it (HID input events seem to
0479 be the exception). This is done via an event-enable request (similarly,
0480 events should be disabled via an event-disable request once no longer
0481 desired).
0482
0483 The specific request used to enable (or disable) an event is given via an
0484 event registry, i.e. the governing authority of this event (so to speak),
0485 represented by |ssam_event_registry|. As parameters to this request, the
0486 target category and, depending on the event registry, instance ID of the
0487 event to be enabled must be provided. This (optional) instance ID must be
0488 zero if the registry does not use it. Together, target category and instance
0489 ID form the event ID, represented by |ssam_event_id|. In short, both, event
0490 registry and event ID, are required to uniquely identify a respective class
0491 of events.
0492
0493 Note that a further *request ID* parameter must be provided for the
0494 enable-event request. This parameter does not influence the class of events
0495 being enabled, but instead is set as the request ID (RQID) on each event of
0496 this class sent by the EC. It is used to identify events (as a limited
0497 number of request IDs is reserved for use in events only, specifically one
0498 to ``SSH_NUM_EVENTS`` inclusively) and also map events to their specific
0499 class. Currently, the controller always sets this parameter to the target
0500 category specified in |ssam_event_id|.
0501
0502 As multiple client drivers may rely on the same (or overlapping) classes of
0503 events and enable/disable calls are strictly binary (i.e. on/off), the
0504 controller has to manage access to these events. It does so via reference
0505 counting, storing the counter inside an RB-tree based mapping with event
0506 registry and ID as key (there is no known list of valid event registry and
0507 event ID combinations). See |ssam_nf|, |ssam_nf_refcount_inc|, and
0508 |ssam_nf_refcount_dec| for details.
0509
0510 This management is done together with notifier registration (described in
0511 the next section) via the top-level |ssam_notifier_register| and
0512 |ssam_notifier_unregister| functions.
0513
0514 Event Delivery
0515 --------------
0516
0517 To receive events, a client driver has to register an event notifier via
0518 |ssam_notifier_register|. This increments the reference counter for that
0519 specific class of events (as detailed in the previous section), enables the
0520 class on the EC (if it has not been enabled already), and installs the
0521 provided notifier callback.
0522
0523 Notifier callbacks are stored in lists, with one (RCU) list per target
0524 category (provided via the event ID; NB: there is a fixed known number of
0525 target categories). There is no known association from the combination of
0526 event registry and event ID to the command data (target ID, target category,
0527 command ID, and instance ID) that can be provided by an event class, apart
0528 from target category and instance ID given via the event ID.
0529
0530 Note that due to the way notifiers are (or rather have to be) stored, client
0531 drivers may receive events that they have not requested and need to account
0532 for them. Specifically, they will, by default, receive all events from the
0533 same target category. To simplify dealing with this, filtering of events by
0534 target ID (provided via the event registry) and instance ID (provided via
0535 the event ID) can be requested when registering a notifier. This filtering
0536 is applied when iterating over the notifiers at the time they are executed.
0537
0538 All notifier callbacks are executed on a dedicated workqueue, the so-called
0539 completion workqueue. After an event has been received via the callback
0540 installed in the request layer (running on the receiver thread of the packet
0541 transport layer), it will be put on its respective event queue
0542 (|ssam_event_queue|). From this event queue the completion work item of that
0543 queue (running on the completion workqueue) will pick up the event and
0544 execute the notifier callback. This is done to avoid blocking on the
0545 receiver thread.
0546
0547 There is one event queue per combination of target ID and target category.
0548 This is done to ensure that notifier callbacks are executed in sequence for
0549 events of the same target ID and target category. Callbacks can be executed
0550 in parallel for events with a different combination of target ID and target
0551 category.
0552
0553 Concurrency and Locking
0554 -----------------------
0555
0556 Most of the concurrency related safety guarantees of the controller are
0557 provided by the lower-level request transport layer. In addition to this,
0558 event (un-)registration is guarded by its own lock.
0559
0560 Access to the controller state is guarded by the state lock. This lock is a
0561 read/write semaphore. The reader part can be used to ensure that the state
0562 does not change while functions depending on the state to stay the same
0563 (e.g. |ssam_notifier_register|, |ssam_notifier_unregister|,
0564 |ssam_request_sync_submit|, and derivatives) are executed and this guarantee
0565 is not already provided otherwise (e.g. through |ssam_client_bind| or
0566 |ssam_client_link|). The writer part guards any transitions that will change
0567 the state, i.e. initialization, destruction, suspension, and resumption.
0568
0569 The controller state may be accessed (read-only) outside the state lock for
0570 smoke-testing against invalid API usage (e.g. in |ssam_request_sync_submit|).
0571 Note that such checks are not supposed to (and will not) protect against all
0572 invalid usages, but rather aim to help catch them. In those cases, proper
0573 variable access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``.
0574
0575 Assuming any preconditions on the state not changing have been satisfied,
0576 all non-initialization and non-shutdown functions may run concurrently with
0577 each other. This includes |ssam_notifier_register|, |ssam_notifier_unregister|,
0578 |ssam_request_sync_submit|, as well as all functions building on top of those.