internal.rst 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. .. SPDX-License-Identifier: GPL-2.0+
  2. .. |ssh_ptl| replace:: :c:type:`struct ssh_ptl <ssh_ptl>`
  3. .. |ssh_ptl_submit| replace:: :c:func:`ssh_ptl_submit`
  4. .. |ssh_ptl_cancel| replace:: :c:func:`ssh_ptl_cancel`
  5. .. |ssh_ptl_shutdown| replace:: :c:func:`ssh_ptl_shutdown`
  6. .. |ssh_ptl_rx_rcvbuf| replace:: :c:func:`ssh_ptl_rx_rcvbuf`
  7. .. |ssh_rtl| replace:: :c:type:`struct ssh_rtl <ssh_rtl>`
  8. .. |ssh_rtl_submit| replace:: :c:func:`ssh_rtl_submit`
  9. .. |ssh_rtl_cancel| replace:: :c:func:`ssh_rtl_cancel`
  10. .. |ssh_rtl_shutdown| replace:: :c:func:`ssh_rtl_shutdown`
  11. .. |ssh_packet| replace:: :c:type:`struct ssh_packet <ssh_packet>`
  12. .. |ssh_packet_get| replace:: :c:func:`ssh_packet_get`
  13. .. |ssh_packet_put| replace:: :c:func:`ssh_packet_put`
  14. .. |ssh_packet_ops| replace:: :c:type:`struct ssh_packet_ops <ssh_packet_ops>`
  15. .. |ssh_packet_base_priority| replace:: :c:type:`enum ssh_packet_base_priority <ssh_packet_base_priority>`
  16. .. |ssh_packet_flags| replace:: :c:type:`enum ssh_packet_flags <ssh_packet_flags>`
  17. .. |SSH_PACKET_PRIORITY| replace:: :c:func:`SSH_PACKET_PRIORITY`
  18. .. |ssh_frame| replace:: :c:type:`struct ssh_frame <ssh_frame>`
  19. .. |ssh_command| replace:: :c:type:`struct ssh_command <ssh_command>`
  20. .. |ssh_request| replace:: :c:type:`struct ssh_request <ssh_request>`
  21. .. |ssh_request_get| replace:: :c:func:`ssh_request_get`
  22. .. |ssh_request_put| replace:: :c:func:`ssh_request_put`
  23. .. |ssh_request_ops| replace:: :c:type:`struct ssh_request_ops <ssh_request_ops>`
  24. .. |ssh_request_init| replace:: :c:func:`ssh_request_init`
  25. .. |ssh_request_flags| replace:: :c:type:`enum ssh_request_flags <ssh_request_flags>`
  26. .. |ssam_controller| replace:: :c:type:`struct ssam_controller <ssam_controller>`
  27. .. |ssam_device| replace:: :c:type:`struct ssam_device <ssam_device>`
  28. .. |ssam_device_driver| replace:: :c:type:`struct ssam_device_driver <ssam_device_driver>`
  29. .. |ssam_client_bind| replace:: :c:func:`ssam_client_bind`
  30. .. |ssam_client_link| replace:: :c:func:`ssam_client_link`
  31. .. |ssam_request_sync| replace:: :c:type:`struct ssam_request_sync <ssam_request_sync>`
  32. .. |ssam_event_registry| replace:: :c:type:`struct ssam_event_registry <ssam_event_registry>`
  33. .. |ssam_event_id| replace:: :c:type:`struct ssam_event_id <ssam_event_id>`
  34. .. |ssam_nf| replace:: :c:type:`struct ssam_nf <ssam_nf>`
  35. .. |ssam_nf_refcount_inc| replace:: :c:func:`ssam_nf_refcount_inc`
  36. .. |ssam_nf_refcount_dec| replace:: :c:func:`ssam_nf_refcount_dec`
  37. .. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register`
  38. .. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister`
  39. .. |ssam_cplt| replace:: :c:type:`struct ssam_cplt <ssam_cplt>`
  40. .. |ssam_event_queue| replace:: :c:type:`struct ssam_event_queue <ssam_event_queue>`
  41. .. |ssam_request_sync_submit| replace:: :c:func:`ssam_request_sync_submit`
  42. =====================
  43. Core Driver Internals
  44. =====================
  45. Architectural overview of the Surface System Aggregator Module (SSAM) core
  46. and Surface Serial Hub (SSH) driver. For the API documentation, refer to:
  47. .. toctree::
  48. :maxdepth: 2
  49. internal-api
  50. Overview
  51. ========
  52. The SSAM core implementation is structured in layers, somewhat following the
  53. SSH protocol structure:
  54. Lower-level packet transport is implemented in the *packet transport layer
  55. (PTL)*, directly building on top of the serial device (serdev)
  56. infrastructure of the kernel. As the name indicates, this layer deals with
  57. the packet transport logic and handles things like packet validation, packet
  58. acknowledgment (ACKing), packet (retransmission) timeouts, and relaying
  59. packet payloads to higher-level layers.
  60. Above this sits the *request transport layer (RTL)*. This layer is centered
  61. around command-type packet payloads, i.e. requests (sent from host to EC),
  62. responses of the EC to those requests, and events (sent from EC to host).
  63. It, specifically, distinguishes events from request responses, matches
  64. responses to their corresponding requests, and implements request timeouts.
  65. The *controller* layer is building on top of this and essentially decides
  66. how request responses and, especially, events are dealt with. It provides an
  67. event notifier system, handles event activation/deactivation, provides a
  68. workqueue for event and asynchronous request completion, and also manages
  69. the message counters required for building command messages (``SEQ``,
  70. ``RQID``). This layer basically provides a fundamental interface to the SAM
  71. EC for use in other kernel drivers.
  72. While the controller layer already provides an interface for other kernel
  73. drivers, the client *bus* extends this interface to provide support for
  74. native SSAM devices, i.e. devices that are not defined in ACPI and not
  75. implemented as platform devices, via |ssam_device| and |ssam_device_driver|
  76. simplify management of client devices and client drivers.
  77. Refer to Documentation/driver-api/surface_aggregator/client.rst for
  78. documentation regarding the client device/driver API and interface options
  79. for other kernel drivers. It is recommended to familiarize oneself with
  80. that chapter and the Documentation/driver-api/surface_aggregator/ssh.rst
  81. before continuing with the architectural overview below.
  82. Packet Transport Layer
  83. ======================
  84. The packet transport layer is represented via |ssh_ptl| and is structured
  85. around the following key concepts:
  86. Packets
  87. -------
  88. Packets are the fundamental transmission unit of the SSH protocol. They are
  89. managed by the packet transport layer, which is essentially the lowest layer
  90. of the driver and is built upon by other components of the SSAM core.
  91. Packets to be transmitted by the SSAM core are represented via |ssh_packet|
  92. (in contrast, packets received by the core do not have any specific
  93. structure and are managed entirely via the raw |ssh_frame|).
  94. This structure contains the required fields to manage the packet inside the
  95. transport layer, as well as a reference to the buffer containing the data to
  96. be transmitted (i.e. the message wrapped in |ssh_frame|). Most notably, it
  97. contains an internal reference count, which is used for managing its
  98. lifetime (accessible via |ssh_packet_get| and |ssh_packet_put|). When this
  99. counter reaches zero, the ``release()`` callback provided to the packet via
  100. its |ssh_packet_ops| reference is executed, which may then deallocate the
  101. packet or its enclosing structure (e.g. |ssh_request|).
  102. In addition to the ``release`` callback, the |ssh_packet_ops| reference also
  103. provides a ``complete()`` callback, which is run once the packet has been
  104. completed and provides the status of this completion, i.e. zero on success
  105. or a negative errno value in case of an error. Once the packet has been
  106. submitted to the packet transport layer, the ``complete()`` callback is
  107. always guaranteed to be executed before the ``release()`` callback, i.e. the
  108. packet will always be completed, either successfully, with an error, or due
  109. to cancellation, before it will be released.
  110. The state of a packet is managed via its ``state`` flags
  111. (|ssh_packet_flags|), which also contains the packet type. In particular,
  112. the following bits are noteworthy:
  113. * ``SSH_PACKET_SF_LOCKED_BIT``: This bit is set when completion, either
  114. through error or success, is imminent. It indicates that no further
  115. references of the packet should be taken and any existing references
  116. should be dropped as soon as possible. The process setting this bit is
  117. responsible for removing any references to this packet from the packet
  118. queue and pending set.
  119. * ``SSH_PACKET_SF_COMPLETED_BIT``: This bit is set by the process running the
  120. ``complete()`` callback and is used to ensure that this callback only runs
  121. once.
  122. * ``SSH_PACKET_SF_QUEUED_BIT``: This bit is set when the packet is queued on
  123. the packet queue and cleared when it is dequeued.
  124. * ``SSH_PACKET_SF_PENDING_BIT``: This bit is set when the packet is added to
  125. the pending set and cleared when it is removed from it.
  126. Packet Queue
  127. ------------
  128. The packet queue is the first of the two fundamental collections in the
  129. packet transport layer. It is a priority queue, with priority of the
  130. respective packets based on the packet type (major) and number of tries
  131. (minor). See |SSH_PACKET_PRIORITY| for more details on the priority value.
  132. All packets to be transmitted by the transport layer must be submitted to
  133. this queue via |ssh_ptl_submit|. Note that this includes control packets
  134. sent by the transport layer itself. Internally, data packets can be
  135. re-submitted to this queue due to timeouts or NAK packets sent by the EC.
  136. Pending Set
  137. -----------
  138. The pending set is the second of the two fundamental collections in the
  139. packet transport layer. It stores references to packets that have already
  140. been transmitted, but wait for acknowledgment (e.g. the corresponding ACK
  141. packet) by the EC.
  142. Note that a packet may both be pending and queued if it has been
  143. re-submitted due to a packet acknowledgment timeout or NAK. On such a
  144. re-submission, packets are not removed from the pending set.
  145. Transmitter Thread
  146. ------------------
  147. The transmitter thread is responsible for most of the actual work regarding
  148. packet transmission. In each iteration, it (waits for and) checks if the
  149. next packet on the queue (if any) can be transmitted and, if so, removes it
  150. from the queue and increments its counter for the number of transmission
  151. attempts, i.e. tries. If the packet is sequenced, i.e. requires an ACK by
  152. the EC, the packet is added to the pending set. Next, the packet's data is
  153. submitted to the serdev subsystem. In case of an error or timeout during
  154. this submission, the packet is completed by the transmitter thread with the
  155. status value of the callback set accordingly. In case the packet is
  156. unsequenced, i.e. does not require an ACK by the EC, the packet is completed
  157. with success on the transmitter thread.
  158. Transmission of sequenced packets is limited by the number of concurrently
  159. pending packets, i.e. a limit on how many packets may be waiting for an ACK
  160. from the EC in parallel. This limit is currently set to one (see
  161. Documentation/driver-api/surface_aggregator/ssh.rst for the reasoning behind
  162. this). Control packets (i.e. ACK and NAK) can always be transmitted.
  163. Receiver Thread
  164. ---------------
  165. Any data received from the EC is put into a FIFO buffer for further
  166. processing. This processing happens on the receiver thread. The receiver
  167. thread parses and validates the received message into its |ssh_frame| and
  168. corresponding payload. It prepares and submits the necessary ACK (and on
  169. validation error or invalid data NAK) packets for the received messages.
  170. This thread also handles further processing, such as matching ACK messages
  171. to the corresponding pending packet (via sequence ID) and completing it, as
  172. well as initiating re-submission of all currently pending packets on
  173. receival of a NAK message (re-submission in case of a NAK is similar to
  174. re-submission due to timeout, see below for more details on that). Note that
  175. the successful completion of a sequenced packet will always run on the
  176. receiver thread (whereas any failure-indicating completion will run on the
  177. process where the failure occurred).
  178. Any payload data is forwarded via a callback to the next upper layer, i.e.
  179. the request transport layer.
  180. Timeout Reaper
  181. --------------
  182. The packet acknowledgment timeout is a per-packet timeout for sequenced
  183. packets, started when the respective packet begins (re-)transmission (i.e.
  184. this timeout is armed once per transmission attempt on the transmitter
  185. thread). It is used to trigger re-submission or, when the number of tries
  186. has been exceeded, cancellation of the packet in question.
  187. This timeout is handled via a dedicated reaper task, which is essentially a
  188. work item (re-)scheduled to run when the next packet is set to time out. The
  189. work item then checks the set of pending packets for any packets that have
  190. exceeded the timeout and, if there are any remaining packets, re-schedules
  191. itself to the next appropriate point in time.
  192. If a timeout has been detected by the reaper, the packet will either be
  193. re-submitted if it still has some remaining tries left, or completed with
  194. ``-ETIMEDOUT`` as status if not. Note that re-submission, in this case and
  195. triggered by receival of a NAK, means that the packet is added to the queue
  196. with a now incremented number of tries, yielding a higher priority. The
  197. timeout for the packet will be disabled until the next transmission attempt
  198. and the packet remains on the pending set.
  199. Note that due to transmission and packet acknowledgment timeouts, the packet
  200. transport layer is always guaranteed to make progress, if only through
  201. timing out packets, and will never fully block.
  202. Concurrency and Locking
  203. -----------------------
  204. There are two main locks in the packet transport layer: One guarding access
  205. to the packet queue and one guarding access to the pending set. These
  206. collections may only be accessed and modified under the respective lock. If
  207. access to both collections is needed, the pending lock must be acquired
  208. before the queue lock to avoid deadlocks.
  209. In addition to guarding the collections, after initial packet submission
  210. certain packet fields may only be accessed under one of the locks.
  211. Specifically, the packet priority must only be accessed while holding the
  212. queue lock and the packet timestamp must only be accessed while holding the
  213. pending lock.
  214. Other parts of the packet transport layer are guarded independently. State
  215. flags are managed by atomic bit operations and, if necessary, memory
  216. barriers. Modifications to the timeout reaper work item and expiration date
  217. are guarded by their own lock.
  218. The reference of the packet to the packet transport layer (``ptl``) is
  219. somewhat special. It is either set when the upper layer request is submitted
  220. or, if there is none, when the packet is first submitted. After it is set,
  221. it will not change its value. Functions that may run concurrently with
  222. submission, i.e. cancellation, can not rely on the ``ptl`` reference to be
  223. set. Access to it in these functions is guarded by ``READ_ONCE()``, whereas
  224. setting ``ptl`` is equally guarded with ``WRITE_ONCE()`` for symmetry.
  225. Some packet fields may be read outside of the respective locks guarding
  226. them, specifically priority and state for tracing. In those cases, proper
  227. access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such
  228. read-only access is only allowed when stale values are not critical.
  229. With respect to the interface for higher layers, packet submission
  230. (|ssh_ptl_submit|), packet cancellation (|ssh_ptl_cancel|), data receival
  231. (|ssh_ptl_rx_rcvbuf|), and layer shutdown (|ssh_ptl_shutdown|) may always be
  232. executed concurrently with respect to each other. Note that packet
  233. submission may not run concurrently with itself for the same packet.
  234. Equally, shutdown and data receival may also not run concurrently with
  235. themselves (but may run concurrently with each other).
  236. Request Transport Layer
  237. =======================
  238. The request transport layer is represented via |ssh_rtl| and builds on top
  239. of the packet transport layer. It deals with requests, i.e. SSH packets sent
  240. by the host containing a |ssh_command| as frame payload. This layer
  241. separates responses to requests from events, which are also sent by the EC
  242. via a |ssh_command| payload. While responses are handled in this layer,
  243. events are relayed to the next upper layer, i.e. the controller layer, via
  244. the corresponding callback. The request transport layer is structured around
  245. the following key concepts:
  246. Request
  247. -------
  248. Requests are packets with a command-type payload, sent from host to EC to
  249. query data from or trigger an action on it (or both simultaneously). They
  250. are represented by |ssh_request|, wrapping the underlying |ssh_packet|
  251. storing its message data (i.e. SSH frame with command payload). Note that
  252. all top-level representations, e.g. |ssam_request_sync| are built upon this
  253. struct.
  254. As |ssh_request| extends |ssh_packet|, its lifetime is also managed by the
  255. reference counter inside the packet struct (which can be accessed via
  256. |ssh_request_get| and |ssh_request_put|). Once the counter reaches zero, the
  257. ``release()`` callback of the |ssh_request_ops| reference of the request is
  258. called.
  259. Requests can have an optional response that is equally sent via a SSH
  260. message with command-type payload (from EC to host). The party constructing
  261. the request must know if a response is expected and mark this in the request
  262. flags provided to |ssh_request_init|, so that the request transport layer
  263. can wait for this response.
  264. Similar to |ssh_packet|, |ssh_request| also has a ``complete()`` callback
  265. provided via its request ops reference and is guaranteed to be completed
  266. before it is released once it has been submitted to the request transport
  267. layer via |ssh_rtl_submit|. For a request without a response, successful
  268. completion will occur once the underlying packet has been successfully
  269. transmitted by the packet transport layer (i.e. from within the packet
  270. completion callback). For a request with response, successful completion
  271. will occur once the response has been received and matched to the request
  272. via its request ID (which happens on the packet layer's data-received
  273. callback running on the receiver thread). If the request is completed with
  274. an error, the status value will be set to the corresponding (negative) errno
  275. value.
  276. The state of a request is again managed via its ``state`` flags
  277. (|ssh_request_flags|), which also encode the request type. In particular,
  278. the following bits are noteworthy:
  279. * ``SSH_REQUEST_SF_LOCKED_BIT``: This bit is set when completion, either
  280. through error or success, is imminent. It indicates that no further
  281. references of the request should be taken and any existing references
  282. should be dropped as soon as possible. The process setting this bit is
  283. responsible for removing any references to this request from the request
  284. queue and pending set.
  285. * ``SSH_REQUEST_SF_COMPLETED_BIT``: This bit is set by the process running the
  286. ``complete()`` callback and is used to ensure that this callback only runs
  287. once.
  288. * ``SSH_REQUEST_SF_QUEUED_BIT``: This bit is set when the request is queued on
  289. the request queue and cleared when it is dequeued.
  290. * ``SSH_REQUEST_SF_PENDING_BIT``: This bit is set when the request is added to
  291. the pending set and cleared when it is removed from it.
  292. Request Queue
  293. -------------
  294. The request queue is the first of the two fundamental collections in the
  295. request transport layer. In contrast to the packet queue of the packet
  296. transport layer, it is not a priority queue and the simple first come first
  297. serve principle applies.
  298. All requests to be transmitted by the request transport layer must be
  299. submitted to this queue via |ssh_rtl_submit|. Once submitted, requests may
  300. not be re-submitted, and will not be re-submitted automatically on timeout.
  301. Instead, the request is completed with a timeout error. If desired, the
  302. caller can create and submit a new request for another try, but it must not
  303. submit the same request again.
  304. Pending Set
  305. -----------
  306. The pending set is the second of the two fundamental collections in the
  307. request transport layer. This collection stores references to all pending
  308. requests, i.e. requests awaiting a response from the EC (similar to what the
  309. pending set of the packet transport layer does for packets).
  310. Transmitter Task
  311. ----------------
  312. The transmitter task is scheduled when a new request is available for
  313. transmission. It checks if the next request on the request queue can be
  314. transmitted and, if so, submits its underlying packet to the packet
  315. transport layer. This check ensures that only a limited number of
  316. requests can be pending, i.e. waiting for a response, at the same time. If
  317. the request requires a response, the request is added to the pending set
  318. before its packet is submitted.
  319. Packet Completion Callback
  320. --------------------------
  321. The packet completion callback is executed once the underlying packet of a
  322. request has been completed. In case of an error completion, the
  323. corresponding request is completed with the error value provided in this
  324. callback.
  325. On successful packet completion, further processing depends on the request.
  326. If the request expects a response, it is marked as transmitted and the
  327. request timeout is started. If the request does not expect a response, it is
  328. completed with success.
  329. Data-Received Callback
  330. ----------------------
  331. The data received callback notifies the request transport layer of data
  332. being received by the underlying packet transport layer via a data-type
  333. frame. In general, this is expected to be a command-type payload.
  334. If the request ID of the command is one of the request IDs reserved for
  335. events (one to ``SSH_NUM_EVENTS``, inclusively), it is forwarded to the
  336. event callback registered in the request transport layer. If the request ID
  337. indicates a response to a request, the respective request is looked up in
  338. the pending set and, if found and marked as transmitted, completed with
  339. success.
  340. Timeout Reaper
  341. --------------
  342. The request-response-timeout is a per-request timeout for requests expecting
  343. a response. It is used to ensure that a request does not wait indefinitely
  344. on a response from the EC and is started after the underlying packet has
  345. been successfully completed.
  346. This timeout is, similar to the packet acknowledgment timeout on the packet
  347. transport layer, handled via a dedicated reaper task. This task is
  348. essentially a work-item (re-)scheduled to run when the next request is set
  349. to time out. The work item then scans the set of pending requests for any
  350. requests that have timed out and completes them with ``-ETIMEDOUT`` as
  351. status. Requests will not be re-submitted automatically. Instead, the issuer
  352. of the request must construct and submit a new request, if so desired.
  353. Note that this timeout, in combination with packet transmission and
  354. acknowledgment timeouts, guarantees that the request layer will always make
  355. progress, even if only through timing out packets, and never fully block.
  356. Concurrency and Locking
  357. -----------------------
  358. Similar to the packet transport layer, there are two main locks in the
  359. request transport layer: One guarding access to the request queue and one
  360. guarding access to the pending set. These collections may only be accessed
  361. and modified under the respective lock.
  362. Other parts of the request transport layer are guarded independently. State
  363. flags are (again) managed by atomic bit operations and, if necessary, memory
  364. barriers. Modifications to the timeout reaper work item and expiration date
  365. are guarded by their own lock.
  366. Some request fields may be read outside of the respective locks guarding
  367. them, specifically the state for tracing. In those cases, proper access is
  368. ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such read-only
  369. access is only allowed when stale values are not critical.
  370. With respect to the interface for higher layers, request submission
  371. (|ssh_rtl_submit|), request cancellation (|ssh_rtl_cancel|), and layer
  372. shutdown (|ssh_rtl_shutdown|) may always be executed concurrently with
  373. respect to each other. Note that request submission may not run concurrently
  374. with itself for the same request (and also may only be called once per
  375. request). Equally, shutdown may also not run concurrently with itself.
  376. Controller Layer
  377. ================
  378. The controller layer extends on the request transport layer to provide an
  379. easy-to-use interface for client drivers. It is represented by
  380. |ssam_controller| and the SSH driver. While the lower level transport layers
  381. take care of transmitting and handling packets and requests, the controller
  382. layer takes on more of a management role. Specifically, it handles device
  383. initialization, power management, and event handling, including event
  384. delivery and registration via the (event) completion system (|ssam_cplt|).
  385. Event Registration
  386. ------------------
  387. In general, an event (or rather a class of events) has to be explicitly
  388. requested by the host before the EC will send it (HID input events seem to
  389. be the exception). This is done via an event-enable request (similarly,
  390. events should be disabled via an event-disable request once no longer
  391. desired).
  392. The specific request used to enable (or disable) an event is given via an
  393. event registry, i.e. the governing authority of this event (so to speak),
  394. represented by |ssam_event_registry|. As parameters to this request, the
  395. target category and, depending on the event registry, instance ID of the
  396. event to be enabled must be provided. This (optional) instance ID must be
  397. zero if the registry does not use it. Together, target category and instance
  398. ID form the event ID, represented by |ssam_event_id|. In short, both, event
  399. registry and event ID, are required to uniquely identify a respective class
  400. of events.
  401. Note that a further *request ID* parameter must be provided for the
  402. enable-event request. This parameter does not influence the class of events
  403. being enabled, but instead is set as the request ID (RQID) on each event of
  404. this class sent by the EC. It is used to identify events (as a limited
  405. number of request IDs is reserved for use in events only, specifically one
  406. to ``SSH_NUM_EVENTS`` inclusively) and also map events to their specific
  407. class. Currently, the controller always sets this parameter to the target
  408. category specified in |ssam_event_id|.
  409. As multiple client drivers may rely on the same (or overlapping) classes of
  410. events and enable/disable calls are strictly binary (i.e. on/off), the
  411. controller has to manage access to these events. It does so via reference
  412. counting, storing the counter inside an RB-tree based mapping with event
  413. registry and ID as key (there is no known list of valid event registry and
  414. event ID combinations). See |ssam_nf|, |ssam_nf_refcount_inc|, and
  415. |ssam_nf_refcount_dec| for details.
  416. This management is done together with notifier registration (described in
  417. the next section) via the top-level |ssam_notifier_register| and
  418. |ssam_notifier_unregister| functions.
  419. Event Delivery
  420. --------------
  421. To receive events, a client driver has to register an event notifier via
  422. |ssam_notifier_register|. This increments the reference counter for that
  423. specific class of events (as detailed in the previous section), enables the
  424. class on the EC (if it has not been enabled already), and installs the
  425. provided notifier callback.
  426. Notifier callbacks are stored in lists, with one (RCU) list per target
  427. category (provided via the event ID; NB: there is a fixed known number of
  428. target categories). There is no known association from the combination of
  429. event registry and event ID to the command data (target ID, target category,
  430. command ID, and instance ID) that can be provided by an event class, apart
  431. from target category and instance ID given via the event ID.
  432. Note that due to the way notifiers are (or rather have to be) stored, client
  433. drivers may receive events that they have not requested and need to account
  434. for them. Specifically, they will, by default, receive all events from the
  435. same target category. To simplify dealing with this, filtering of events by
  436. target ID (provided via the event registry) and instance ID (provided via
  437. the event ID) can be requested when registering a notifier. This filtering
  438. is applied when iterating over the notifiers at the time they are executed.
  439. All notifier callbacks are executed on a dedicated workqueue, the so-called
  440. completion workqueue. After an event has been received via the callback
  441. installed in the request layer (running on the receiver thread of the packet
  442. transport layer), it will be put on its respective event queue
  443. (|ssam_event_queue|). From this event queue the completion work item of that
  444. queue (running on the completion workqueue) will pick up the event and
  445. execute the notifier callback. This is done to avoid blocking on the
  446. receiver thread.
  447. There is one event queue per combination of target ID and target category.
  448. This is done to ensure that notifier callbacks are executed in sequence for
  449. events of the same target ID and target category. Callbacks can be executed
  450. in parallel for events with a different combination of target ID and target
  451. category.
  452. Concurrency and Locking
  453. -----------------------
  454. Most of the concurrency related safety guarantees of the controller are
  455. provided by the lower-level request transport layer. In addition to this,
  456. event (un-)registration is guarded by its own lock.
  457. Access to the controller state is guarded by the state lock. This lock is a
  458. read/write semaphore. The reader part can be used to ensure that the state
  459. does not change while functions depending on the state to stay the same
  460. (e.g. |ssam_notifier_register|, |ssam_notifier_unregister|,
  461. |ssam_request_sync_submit|, and derivatives) are executed and this guarantee
  462. is not already provided otherwise (e.g. through |ssam_client_bind| or
  463. |ssam_client_link|). The writer part guards any transitions that will change
  464. the state, i.e. initialization, destruction, suspension, and resumption.
  465. The controller state may be accessed (read-only) outside the state lock for
  466. smoke-testing against invalid API usage (e.g. in |ssam_request_sync_submit|).
  467. Note that such checks are not supposed to (and will not) protect against all
  468. invalid usages, but rather aim to help catch them. In those cases, proper
  469. variable access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``.
  470. Assuming any preconditions on the state not changing have been satisfied,
  471. all non-initialization and non-shutdown functions may run concurrently with
  472. each other. This includes |ssam_notifier_register|, |ssam_notifier_unregister|,
  473. |ssam_request_sync_submit|, as well as all functions building on top of those.