Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

docs: driver-api: Add Surface Aggregator subsystem documentation

Add documentation for the Surface Aggregator subsystem and its client
drivers, giving an overview of the subsystem, its use-cases, its
internal structure and internal API, as well as its external API for
writing client drivers.

Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-8-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>

authored by

Maximilian Luz and committed by
Hans de Goede
8d779282 eb0e90a8

+1529
+1
Documentation/driver-api/index.rst
··· 99 99 rfkill 100 100 serial/index 101 101 sm501 102 + surface_aggregator/index 102 103 switchtec 103 104 sync_file 104 105 vfio-mediated-device
+38
Documentation/driver-api/surface_aggregator/client-api.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + =============================== 4 + Client Driver API Documentation 5 + =============================== 6 + 7 + .. contents:: 8 + :depth: 2 9 + 10 + 11 + Serial Hub Communication 12 + ======================== 13 + 14 + .. kernel-doc:: include/linux/surface_aggregator/serial_hub.h 15 + 16 + .. kernel-doc:: drivers/platform/surface/aggregator/ssh_packet_layer.c 17 + :export: 18 + 19 + 20 + Controller and Core Interface 21 + ============================= 22 + 23 + .. kernel-doc:: include/linux/surface_aggregator/controller.h 24 + 25 + .. kernel-doc:: drivers/platform/surface/aggregator/controller.c 26 + :export: 27 + 28 + .. kernel-doc:: drivers/platform/surface/aggregator/core.c 29 + :export: 30 + 31 + 32 + Client Bus and Client Device API 33 + ================================ 34 + 35 + .. kernel-doc:: include/linux/surface_aggregator/device.h 36 + 37 + .. kernel-doc:: drivers/platform/surface/aggregator/bus.c 38 + :export:
+393
Documentation/driver-api/surface_aggregator/client.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + .. |ssam_controller| replace:: :c:type:`struct ssam_controller <ssam_controller>` 4 + .. |ssam_device| replace:: :c:type:`struct ssam_device <ssam_device>` 5 + .. |ssam_device_driver| replace:: :c:type:`struct ssam_device_driver <ssam_device_driver>` 6 + .. |ssam_client_bind| replace:: :c:func:`ssam_client_bind` 7 + .. |ssam_client_link| replace:: :c:func:`ssam_client_link` 8 + .. |ssam_get_controller| replace:: :c:func:`ssam_get_controller` 9 + .. |ssam_controller_get| replace:: :c:func:`ssam_controller_get` 10 + .. |ssam_controller_put| replace:: :c:func:`ssam_controller_put` 11 + .. |ssam_device_alloc| replace:: :c:func:`ssam_device_alloc` 12 + .. |ssam_device_add| replace:: :c:func:`ssam_device_add` 13 + .. |ssam_device_remove| replace:: :c:func:`ssam_device_remove` 14 + .. |ssam_device_driver_register| replace:: :c:func:`ssam_device_driver_register` 15 + .. |ssam_device_driver_unregister| replace:: :c:func:`ssam_device_driver_unregister` 16 + .. |module_ssam_device_driver| replace:: :c:func:`module_ssam_device_driver` 17 + .. |SSAM_DEVICE| replace:: :c:func:`SSAM_DEVICE` 18 + .. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register` 19 + .. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister` 20 + .. |ssam_request_sync| replace:: :c:func:`ssam_request_sync` 21 + .. |ssam_event_mask| replace:: :c:type:`enum ssam_event_mask <ssam_event_mask>` 22 + 23 + 24 + ====================== 25 + Writing Client Drivers 26 + ====================== 27 + 28 + For the API documentation, refer to: 29 + 30 + .. toctree:: 31 + :maxdepth: 2 32 + 33 + client-api 34 + 35 + 36 + Overview 37 + ======== 38 + 39 + Client drivers can be set up in two main ways, depending on how the 40 + corresponding device is made available to the system. We specifically 41 + differentiate between devices that are presented to the system via one of 42 + the conventional ways, e.g. as platform devices via ACPI, and devices that 43 + are non-discoverable and instead need to be explicitly provided by some 44 + other mechanism, as discussed further below. 45 + 46 + 47 + Non-SSAM Client Drivers 48 + ======================= 49 + 50 + All communication with the SAM EC is handled via the |ssam_controller| 51 + representing that EC to the kernel. Drivers targeting a non-SSAM device (and 52 + thus not being a |ssam_device_driver|) need to explicitly establish a 53 + connection/relation to that controller. This can be done via the 54 + |ssam_client_bind| function. Said function returns a reference to the SSAM 55 + controller, but, more importantly, also establishes a device link between 56 + client device and controller (this can also be done separate via 57 + |ssam_client_link|). It is important to do this, as it, first, guarantees 58 + that the returned controller is valid for use in the client driver for as 59 + long as this driver is bound to its device, i.e. that the driver gets 60 + unbound before the controller ever becomes invalid, and, second, as it 61 + ensures correct suspend/resume ordering. This setup should be done in the 62 + driver's probe function, and may be used to defer probing in case the SSAM 63 + subsystem is not ready yet, for example: 64 + 65 + .. code-block:: c 66 + 67 + static int client_driver_probe(struct platform_device *pdev) 68 + { 69 + struct ssam_controller *ctrl; 70 + 71 + ctrl = ssam_client_bind(&pdev->dev); 72 + if (IS_ERR(ctrl)) 73 + return PTR_ERR(ctrl) == -ENODEV ? -EPROBE_DEFER : PTR_ERR(ctrl); 74 + 75 + // ... 76 + 77 + return 0; 78 + } 79 + 80 + The controller may be separately obtained via |ssam_get_controller| and its 81 + lifetime be guaranteed via |ssam_controller_get| and |ssam_controller_put|. 82 + Note that none of these functions, however, guarantee that the controller 83 + will not be shut down or suspended. These functions essentially only operate 84 + on the reference, i.e. only guarantee a bare minimum of accessibility 85 + without any guarantees at all on practical operability. 86 + 87 + 88 + Adding SSAM Devices 89 + =================== 90 + 91 + If a device does not already exist/is not already provided via conventional 92 + means, it should be provided as |ssam_device| via the SSAM client device 93 + hub. New devices can be added to this hub by entering their UID into the 94 + corresponding registry. SSAM devices can also be manually allocated via 95 + |ssam_device_alloc|, subsequently to which they have to be added via 96 + |ssam_device_add| and eventually removed via |ssam_device_remove|. By 97 + default, the parent of the device is set to the controller device provided 98 + for allocation, however this may be changed before the device is added. Note 99 + that, when changing the parent device, care must be taken to ensure that the 100 + controller lifetime and suspend/resume ordering guarantees, in the default 101 + setup provided through the parent-child relation, are preserved. If 102 + necessary, by use of |ssam_client_link| as is done for non-SSAM client 103 + drivers and described in more detail above. 104 + 105 + A client device must always be removed by the party which added the 106 + respective device before the controller shuts down. Such removal can be 107 + guaranteed by linking the driver providing the SSAM device to the controller 108 + via |ssam_client_link|, causing it to unbind before the controller driver 109 + unbinds. Client devices registered with the controller as parent are 110 + automatically removed when the controller shuts down, but this should not be 111 + relied upon, especially as this does not extend to client devices with a 112 + different parent. 113 + 114 + 115 + SSAM Client Drivers 116 + =================== 117 + 118 + SSAM client device drivers are, in essence, no different than other device 119 + driver types. They are represented via |ssam_device_driver| and bind to a 120 + |ssam_device| via its UID (:c:type:`struct ssam_device.uid <ssam_device>`) 121 + member and the match table 122 + (:c:type:`struct ssam_device_driver.match_table <ssam_device_driver>`), 123 + which should be set when declaring the driver struct instance. Refer to the 124 + |SSAM_DEVICE| macro documentation for more details on how to define members 125 + of the driver's match table. 126 + 127 + The UID for SSAM client devices consists of a ``domain``, a ``category``, 128 + a ``target``, an ``instance``, and a ``function``. The ``domain`` is used 129 + differentiate between physical SAM devices 130 + (:c:type:`SSAM_DOMAIN_SERIALHUB <ssam_device_domain>`), i.e. devices that can 131 + be accessed via the Surface Serial Hub, and virtual ones 132 + (:c:type:`SSAM_DOMAIN_VIRTUAL <ssam_device_domain>`), such as client-device 133 + hubs, that have no real representation on the SAM EC and are solely used on 134 + the kernel/driver-side. For physical devices, ``category`` represents the 135 + target category, ``target`` the target ID, and ``instance`` the instance ID 136 + used to access the physical SAM device. In addition, ``function`` references 137 + a specific device functionality, but has no meaning to the SAM EC. The 138 + (default) name of a client device is generated based on its UID. 139 + 140 + A driver instance can be registered via |ssam_device_driver_register| and 141 + unregistered via |ssam_device_driver_unregister|. For convenience, the 142 + |module_ssam_device_driver| macro may be used to define module init- and 143 + exit-functions registering the driver. 144 + 145 + The controller associated with a SSAM client device can be found in its 146 + :c:type:`struct ssam_device.ctrl <ssam_device>` member. This reference is 147 + guaranteed to be valid for at least as long as the client driver is bound, 148 + but should also be valid for as long as the client device exists. Note, 149 + however, that access outside of the bound client driver must ensure that the 150 + controller device is not suspended while making any requests or 151 + (un-)registering event notifiers (and thus should generally be avoided). This 152 + is guaranteed when the controller is accessed from inside the bound client 153 + driver. 154 + 155 + 156 + Making Synchronous Requests 157 + =========================== 158 + 159 + Synchronous requests are (currently) the main form of host-initiated 160 + communication with the EC. There are a couple of ways to define and execute 161 + such requests, however, most of them boil down to something similar as shown 162 + in the example below. This example defines a write-read request, meaning 163 + that the caller provides an argument to the SAM EC and receives a response. 164 + The caller needs to know the (maximum) length of the response payload and 165 + provide a buffer for it. 166 + 167 + Care must be taken to ensure that any command payload data passed to the SAM 168 + EC is provided in little-endian format and, similarly, any response payload 169 + data received from it is converted from little-endian to host endianness. 170 + 171 + .. code-block:: c 172 + 173 + int perform_request(struct ssam_controller *ctrl, u32 arg, u32 *ret) 174 + { 175 + struct ssam_request rqst; 176 + struct ssam_response resp; 177 + int status; 178 + 179 + /* Convert request argument to little-endian. */ 180 + __le32 arg_le = cpu_to_le32(arg); 181 + __le32 ret_le = cpu_to_le32(0); 182 + 183 + /* 184 + * Initialize request specification. Replace this with your values. 185 + * The rqst.payload field may be NULL if rqst.length is zero, 186 + * indicating that the request does not have any argument. 187 + * 188 + * Note: The request parameters used here are not valid, i.e. 189 + * they do not correspond to an actual SAM/EC request. 190 + */ 191 + rqst.target_category = SSAM_SSH_TC_SAM; 192 + rqst.target_id = 0x01; 193 + rqst.command_id = 0x02; 194 + rqst.instance_id = 0x03; 195 + rqst.flags = SSAM_REQUEST_HAS_RESPONSE; 196 + rqst.length = sizeof(arg_le); 197 + rqst.payload = (u8 *)&arg_le; 198 + 199 + /* Initialize request response. */ 200 + resp.capacity = sizeof(ret_le); 201 + resp.length = 0; 202 + resp.pointer = (u8 *)&ret_le; 203 + 204 + /* 205 + * Perform actual request. The response pointer may be null in case 206 + * the request does not have any response. This must be consistent 207 + * with the SSAM_REQUEST_HAS_RESPONSE flag set in the specification 208 + * above. 209 + */ 210 + status = ssam_request_sync(ctrl, &rqst, &resp); 211 + 212 + /* 213 + * Alternatively use 214 + * 215 + * ssam_request_sync_onstack(ctrl, &rqst, &resp, sizeof(arg_le)); 216 + * 217 + * to perform the request, allocating the message buffer directly 218 + * on the stack as opposed to allocation via kzalloc(). 219 + */ 220 + 221 + /* 222 + * Convert request response back to native format. Note that in the 223 + * error case, this value is not touched by the SSAM core, i.e. 224 + * 'ret_le' will be zero as specified in its initialization. 225 + */ 226 + *ret = le32_to_cpu(ret_le); 227 + 228 + return status; 229 + } 230 + 231 + Note that |ssam_request_sync| in its essence is a wrapper over lower-level 232 + request primitives, which may also be used to perform requests. Refer to its 233 + implementation and documentation for more details. 234 + 235 + An arguably more user-friendly way of defining such functions is by using 236 + one of the generator macros, for example via: 237 + 238 + .. code-block:: c 239 + 240 + SSAM_DEFINE_SYNC_REQUEST_W(__ssam_tmp_perf_mode_set, __le32, { 241 + .target_category = SSAM_SSH_TC_TMP, 242 + .target_id = 0x01, 243 + .command_id = 0x03, 244 + .instance_id = 0x00, 245 + }); 246 + 247 + This example defines a function 248 + 249 + .. code-block:: c 250 + 251 + int __ssam_tmp_perf_mode_set(struct ssam_controller *ctrl, const __le32 *arg); 252 + 253 + executing the specified request, with the controller passed in when calling 254 + said function. In this example, the argument is provided via the ``arg`` 255 + pointer. Note that the generated function allocates the message buffer on 256 + the stack. Thus, if the argument provided via the request is large, these 257 + kinds of macros should be avoided. Also note that, in contrast to the 258 + previous non-macro example, this function does not do any endianness 259 + conversion, which has to be handled by the caller. Apart from those 260 + differences the function generated by the macro is similar to the one 261 + provided in the non-macro example above. 262 + 263 + The full list of such function-generating macros is 264 + 265 + - :c:func:`SSAM_DEFINE_SYNC_REQUEST_N` for requests without return value and 266 + without argument. 267 + - :c:func:`SSAM_DEFINE_SYNC_REQUEST_R` for requests with return value but no 268 + argument. 269 + - :c:func:`SSAM_DEFINE_SYNC_REQUEST_W` for requests without return value but 270 + with argument. 271 + 272 + Refer to their respective documentation for more details. For each one of 273 + these macros, a special variant is provided, which targets request types 274 + applicable to multiple instances of the same device type: 275 + 276 + - :c:func:`SSAM_DEFINE_SYNC_REQUEST_MD_N` 277 + - :c:func:`SSAM_DEFINE_SYNC_REQUEST_MD_R` 278 + - :c:func:`SSAM_DEFINE_SYNC_REQUEST_MD_W` 279 + 280 + The difference of those macros to the previously mentioned versions is, that 281 + the device target and instance IDs are not fixed for the generated function, 282 + but instead have to be provided by the caller of said function. 283 + 284 + Additionally, variants for direct use with client devices, i.e. 285 + |ssam_device|, are also provided. These can, for example, be used as 286 + follows: 287 + 288 + .. code-block:: c 289 + 290 + SSAM_DEFINE_SYNC_REQUEST_CL_R(ssam_bat_get_sta, __le32, { 291 + .target_category = SSAM_SSH_TC_BAT, 292 + .command_id = 0x01, 293 + }); 294 + 295 + This invocation of the macro defines a function 296 + 297 + .. code-block:: c 298 + 299 + int ssam_bat_get_sta(struct ssam_device *sdev, __le32 *ret); 300 + 301 + executing the specified request, using the device IDs and controller given 302 + in the client device. The full list of such macros for client devices is: 303 + 304 + - :c:func:`SSAM_DEFINE_SYNC_REQUEST_CL_N` 305 + - :c:func:`SSAM_DEFINE_SYNC_REQUEST_CL_R` 306 + - :c:func:`SSAM_DEFINE_SYNC_REQUEST_CL_W` 307 + 308 + 309 + Handling Events 310 + =============== 311 + 312 + To receive events from the SAM EC, an event notifier must be registered for 313 + the desired event via |ssam_notifier_register|. The notifier must be 314 + unregistered via |ssam_notifier_unregister| once it is not required any 315 + more. 316 + 317 + Event notifiers are registered by providing (at minimum) a callback to call 318 + in case an event has been received, the registry specifying how the event 319 + should be enabled, an event ID specifying for which target category and, 320 + optionally and depending on the registry used, for which instance ID events 321 + should be enabled, and finally, flags describing how the EC will send these 322 + events. If the specific registry does not enable events by instance ID, the 323 + instance ID must be set to zero. Additionally, a priority for the respective 324 + notifier may be specified, which determines its order in relation to any 325 + other notifier registered for the same target category. 326 + 327 + By default, event notifiers will receive all events for the specific target 328 + category, regardless of the instance ID specified when registering the 329 + notifier. The core may be instructed to only call a notifier if the target 330 + ID or instance ID (or both) of the event match the ones implied by the 331 + notifier IDs (in case of target ID, the target ID of the registry), by 332 + providing an event mask (see |ssam_event_mask|). 333 + 334 + In general, the target ID of the registry is also the target ID of the 335 + enabled event (with the notable exception being keyboard input events on the 336 + Surface Laptop 1 and 2, which are enabled via a registry with target ID 1, 337 + but provide events with target ID 2). 338 + 339 + A full example for registering an event notifier and handling received 340 + events is provided below: 341 + 342 + .. code-block:: c 343 + 344 + u32 notifier_callback(struct ssam_event_notifier *nf, 345 + const struct ssam_event *event) 346 + { 347 + int status = ... 348 + 349 + /* Handle the event here ... */ 350 + 351 + /* Convert return value and indicate that we handled the event. */ 352 + return ssam_notifier_from_errno(status) | SSAM_NOTIF_HANDLED; 353 + } 354 + 355 + int setup_notifier(struct ssam_device *sdev, 356 + struct ssam_event_notifier *nf) 357 + { 358 + /* Set priority wrt. other handlers of same target category. */ 359 + nf->base.priority = 1; 360 + 361 + /* Set event/notifier callback. */ 362 + nf->base.fn = notifier_callback; 363 + 364 + /* Specify event registry, i.e. how events get enabled/disabled. */ 365 + nf->event.reg = SSAM_EVENT_REGISTRY_KIP; 366 + 367 + /* Specify which event to enable/disable */ 368 + nf->event.id.target_category = sdev->uid.category; 369 + nf->event.id.instance = sdev->uid.instance; 370 + 371 + /* 372 + * Specify for which events the notifier callback gets executed. 373 + * This essentially tells the core if it can skip notifiers that 374 + * don't have target or instance IDs matching those of the event. 375 + */ 376 + nf->event.mask = SSAM_EVENT_MASK_STRICT; 377 + 378 + /* Specify event flags. */ 379 + nf->event.flags = SSAM_EVENT_SEQUENCED; 380 + 381 + return ssam_notifier_register(sdev->ctrl, nf); 382 + } 383 + 384 + Multiple event notifiers can be registered for the same event. The event 385 + handler core takes care of enabling and disabling events when notifiers are 386 + registered and unregistered, by keeping track of how many notifiers for a 387 + specific event (combination of registry, event target category, and event 388 + instance ID) are currently registered. This means that a specific event will 389 + be enabled when the first notifier for it is being registered and disabled 390 + when the last notifier for it is being unregistered. Note that the event 391 + flags are therefore only used on the first registered notifier, however, one 392 + should take care that notifiers for a specific event are always registered 393 + with the same flag and it is considered a bug to do otherwise.
+10
Documentation/driver-api/surface_aggregator/clients/index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + =========================== 4 + Client Driver Documentation 5 + =========================== 6 + 7 + This is the documentation for client drivers themselves. Refer to 8 + :doc:`../client` for documentation on how to write client drivers. 9 + 10 + .. Place documentation for individual client drivers here.
+21
Documentation/driver-api/surface_aggregator/index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + ======================================= 4 + Surface System Aggregator Module (SSAM) 5 + ======================================= 6 + 7 + .. toctree:: 8 + :maxdepth: 2 9 + 10 + overview 11 + client 12 + clients/index 13 + ssh 14 + internal 15 + 16 + .. only:: subproject and html 17 + 18 + Indices 19 + ======= 20 + 21 + * :ref:`genindex`
+67
Documentation/driver-api/surface_aggregator/internal-api.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + ========================== 4 + Internal API Documentation 5 + ========================== 6 + 7 + .. contents:: 8 + :depth: 2 9 + 10 + 11 + Packet Transport Layer 12 + ====================== 13 + 14 + .. kernel-doc:: drivers/platform/surface/aggregator/ssh_parser.h 15 + :internal: 16 + 17 + .. kernel-doc:: drivers/platform/surface/aggregator/ssh_parser.c 18 + :internal: 19 + 20 + .. kernel-doc:: drivers/platform/surface/aggregator/ssh_msgb.h 21 + :internal: 22 + 23 + .. kernel-doc:: drivers/platform/surface/aggregator/ssh_packet_layer.h 24 + :internal: 25 + 26 + .. kernel-doc:: drivers/platform/surface/aggregator/ssh_packet_layer.c 27 + :internal: 28 + 29 + 30 + Request Transport Layer 31 + ======================= 32 + 33 + .. kernel-doc:: drivers/platform/surface/aggregator/ssh_request_layer.h 34 + :internal: 35 + 36 + .. kernel-doc:: drivers/platform/surface/aggregator/ssh_request_layer.c 37 + :internal: 38 + 39 + 40 + Controller 41 + ========== 42 + 43 + .. kernel-doc:: drivers/platform/surface/aggregator/controller.h 44 + :internal: 45 + 46 + .. kernel-doc:: drivers/platform/surface/aggregator/controller.c 47 + :internal: 48 + 49 + 50 + Client Device Bus 51 + ================= 52 + 53 + .. kernel-doc:: drivers/platform/surface/aggregator/bus.c 54 + :internal: 55 + 56 + 57 + Core 58 + ==== 59 + 60 + .. kernel-doc:: drivers/platform/surface/aggregator/core.c 61 + :internal: 62 + 63 + 64 + Trace Helpers 65 + ============= 66 + 67 + .. kernel-doc:: drivers/platform/surface/aggregator/trace.h
+577
Documentation/driver-api/surface_aggregator/internal.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + .. |ssh_ptl| replace:: :c:type:`struct ssh_ptl <ssh_ptl>` 4 + .. |ssh_ptl_submit| replace:: :c:func:`ssh_ptl_submit` 5 + .. |ssh_ptl_cancel| replace:: :c:func:`ssh_ptl_cancel` 6 + .. |ssh_ptl_shutdown| replace:: :c:func:`ssh_ptl_shutdown` 7 + .. |ssh_ptl_rx_rcvbuf| replace:: :c:func:`ssh_ptl_rx_rcvbuf` 8 + .. |ssh_rtl| replace:: :c:type:`struct ssh_rtl <ssh_rtl>` 9 + .. |ssh_rtl_submit| replace:: :c:func:`ssh_rtl_submit` 10 + .. |ssh_rtl_cancel| replace:: :c:func:`ssh_rtl_cancel` 11 + .. |ssh_rtl_shutdown| replace:: :c:func:`ssh_rtl_shutdown` 12 + .. |ssh_packet| replace:: :c:type:`struct ssh_packet <ssh_packet>` 13 + .. |ssh_packet_get| replace:: :c:func:`ssh_packet_get` 14 + .. |ssh_packet_put| replace:: :c:func:`ssh_packet_put` 15 + .. |ssh_packet_ops| replace:: :c:type:`struct ssh_packet_ops <ssh_packet_ops>` 16 + .. |ssh_packet_base_priority| replace:: :c:type:`enum ssh_packet_base_priority <ssh_packet_base_priority>` 17 + .. |ssh_packet_flags| replace:: :c:type:`enum ssh_packet_flags <ssh_packet_flags>` 18 + .. |SSH_PACKET_PRIORITY| replace:: :c:func:`SSH_PACKET_PRIORITY` 19 + .. |ssh_frame| replace:: :c:type:`struct ssh_frame <ssh_frame>` 20 + .. |ssh_command| replace:: :c:type:`struct ssh_command <ssh_command>` 21 + .. |ssh_request| replace:: :c:type:`struct ssh_request <ssh_request>` 22 + .. |ssh_request_get| replace:: :c:func:`ssh_request_get` 23 + .. |ssh_request_put| replace:: :c:func:`ssh_request_put` 24 + .. |ssh_request_ops| replace:: :c:type:`struct ssh_request_ops <ssh_request_ops>` 25 + .. |ssh_request_init| replace:: :c:func:`ssh_request_init` 26 + .. |ssh_request_flags| replace:: :c:type:`enum ssh_request_flags <ssh_request_flags>` 27 + .. |ssam_controller| replace:: :c:type:`struct ssam_controller <ssam_controller>` 28 + .. |ssam_device| replace:: :c:type:`struct ssam_device <ssam_device>` 29 + .. |ssam_device_driver| replace:: :c:type:`struct ssam_device_driver <ssam_device_driver>` 30 + .. |ssam_client_bind| replace:: :c:func:`ssam_client_bind` 31 + .. |ssam_client_link| replace:: :c:func:`ssam_client_link` 32 + .. |ssam_request_sync| replace:: :c:type:`struct ssam_request_sync <ssam_request_sync>` 33 + .. |ssam_event_registry| replace:: :c:type:`struct ssam_event_registry <ssam_event_registry>` 34 + .. |ssam_event_id| replace:: :c:type:`struct ssam_event_id <ssam_event_id>` 35 + .. |ssam_nf| replace:: :c:type:`struct ssam_nf <ssam_nf>` 36 + .. |ssam_nf_refcount_inc| replace:: :c:func:`ssam_nf_refcount_inc` 37 + .. |ssam_nf_refcount_dec| replace:: :c:func:`ssam_nf_refcount_dec` 38 + .. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register` 39 + .. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister` 40 + .. |ssam_cplt| replace:: :c:type:`struct ssam_cplt <ssam_cplt>` 41 + .. |ssam_event_queue| replace:: :c:type:`struct ssam_event_queue <ssam_event_queue>` 42 + .. |ssam_request_sync_submit| replace:: :c:func:`ssam_request_sync_submit` 43 + 44 + ===================== 45 + Core Driver Internals 46 + ===================== 47 + 48 + Architectural overview of the Surface System Aggregator Module (SSAM) core 49 + and Surface Serial Hub (SSH) driver. For the API documentation, refer to: 50 + 51 + .. toctree:: 52 + :maxdepth: 2 53 + 54 + internal-api 55 + 56 + 57 + Overview 58 + ======== 59 + 60 + The SSAM core implementation is structured in layers, somewhat following the 61 + SSH protocol structure: 62 + 63 + Lower-level packet transport is implemented in the *packet transport layer 64 + (PTL)*, directly building on top of the serial device (serdev) 65 + infrastructure of the kernel. As the name indicates, this layer deals with 66 + the packet transport logic and handles things like packet validation, packet 67 + acknowledgment (ACKing), packet (retransmission) timeouts, and relaying 68 + packet payloads to higher-level layers. 69 + 70 + Above this sits the *request transport layer (RTL)*. This layer is centered 71 + around command-type packet payloads, i.e. requests (sent from host to EC), 72 + responses of the EC to those requests, and events (sent from EC to host). 73 + It, specifically, distinguishes events from request responses, matches 74 + responses to their corresponding requests, and implements request timeouts. 75 + 76 + The *controller* layer is building on top of this and essentially decides 77 + how request responses and, especially, events are dealt with. It provides an 78 + event notifier system, handles event activation/deactivation, provides a 79 + workqueue for event and asynchronous request completion, and also manages 80 + the message counters required for building command messages (``SEQ``, 81 + ``RQID``). This layer basically provides a fundamental interface to the SAM 82 + EC for use in other kernel drivers. 83 + 84 + While the controller layer already provides an interface for other kernel 85 + drivers, the client *bus* extends this interface to provide support for 86 + native SSAM devices, i.e. devices that are not defined in ACPI and not 87 + implemented as platform devices, via |ssam_device| and |ssam_device_driver| 88 + simplify management of client devices and client drivers. 89 + 90 + Refer to :doc:`client` for documentation regarding the client device/driver 91 + API and interface options for other kernel drivers. It is recommended to 92 + familiarize oneself with that chapter and the :doc:`ssh` before continuing 93 + with the architectural overview below. 94 + 95 + 96 + Packet Transport Layer 97 + ====================== 98 + 99 + The packet transport layer is represented via |ssh_ptl| and is structured 100 + around the following key concepts: 101 + 102 + Packets 103 + ------- 104 + 105 + Packets are the fundamental transmission unit of the SSH protocol. They are 106 + managed by the packet transport layer, which is essentially the lowest layer 107 + of the driver and is built upon by other components of the SSAM core. 108 + Packets to be transmitted by the SSAM core are represented via |ssh_packet| 109 + (in contrast, packets received by the core do not have any specific 110 + structure and are managed entirely via the raw |ssh_frame|). 111 + 112 + This structure contains the required fields to manage the packet inside the 113 + transport layer, as well as a reference to the buffer containing the data to 114 + be transmitted (i.e. the message wrapped in |ssh_frame|). Most notably, it 115 + contains an internal reference count, which is used for managing its 116 + lifetime (accessible via |ssh_packet_get| and |ssh_packet_put|). When this 117 + counter reaches zero, the ``release()`` callback provided to the packet via 118 + its |ssh_packet_ops| reference is executed, which may then deallocate the 119 + packet or its enclosing structure (e.g. |ssh_request|). 120 + 121 + In addition to the ``release`` callback, the |ssh_packet_ops| reference also 122 + provides a ``complete()`` callback, which is run once the packet has been 123 + completed and provides the status of this completion, i.e. zero on success 124 + or a negative errno value in case of an error. Once the packet has been 125 + submitted to the packet transport layer, the ``complete()`` callback is 126 + always guaranteed to be executed before the ``release()`` callback, i.e. the 127 + packet will always be completed, either successfully, with an error, or due 128 + to cancellation, before it will be released. 129 + 130 + The state of a packet is managed via its ``state`` flags 131 + (|ssh_packet_flags|), which also contains the packet type. In particular, 132 + the following bits are noteworthy: 133 + 134 + * ``SSH_PACKET_SF_LOCKED_BIT``: This bit is set when completion, either 135 + through error or success, is imminent. It indicates that no further 136 + references of the packet should be taken and any existing references 137 + should be dropped as soon as possible. The process setting this bit is 138 + responsible for removing any references to this packet from the packet 139 + queue and pending set. 140 + 141 + * ``SSH_PACKET_SF_COMPLETED_BIT``: This bit is set by the process running the 142 + ``complete()`` callback and is used to ensure that this callback only runs 143 + once. 144 + 145 + * ``SSH_PACKET_SF_QUEUED_BIT``: This bit is set when the packet is queued on 146 + the packet queue and cleared when it is dequeued. 147 + 148 + * ``SSH_PACKET_SF_PENDING_BIT``: This bit is set when the packet is added to 149 + the pending set and cleared when it is removed from it. 150 + 151 + Packet Queue 152 + ------------ 153 + 154 + The packet queue is the first of the two fundamental collections in the 155 + packet transport layer. It is a priority queue, with priority of the 156 + respective packets based on the packet type (major) and number of tries 157 + (minor). See |SSH_PACKET_PRIORITY| for more details on the priority value. 158 + 159 + All packets to be transmitted by the transport layer must be submitted to 160 + this queue via |ssh_ptl_submit|. Note that this includes control packets 161 + sent by the transport layer itself. Internally, data packets can be 162 + re-submitted to this queue due to timeouts or NAK packets sent by the EC. 163 + 164 + Pending Set 165 + ----------- 166 + 167 + The pending set is the second of the two fundamental collections in the 168 + packet transport layer. It stores references to packets that have already 169 + been transmitted, but wait for acknowledgment (e.g. the corresponding ACK 170 + packet) by the EC. 171 + 172 + Note that a packet may both be pending and queued if it has been 173 + re-submitted due to a packet acknowledgment timeout or NAK. On such a 174 + re-submission, packets are not removed from the pending set. 175 + 176 + Transmitter Thread 177 + ------------------ 178 + 179 + The transmitter thread is responsible for most of the actual work regarding 180 + packet transmission. In each iteration, it (waits for and) checks if the 181 + next packet on the queue (if any) can be transmitted and, if so, removes it 182 + from the queue and increments its counter for the number of transmission 183 + attempts, i.e. tries. If the packet is sequenced, i.e. requires an ACK by 184 + the EC, the packet is added to the pending set. Next, the packet's data is 185 + submitted to the serdev subsystem. In case of an error or timeout during 186 + this submission, the packet is completed by the transmitter thread with the 187 + status value of the callback set accordingly. In case the packet is 188 + unsequenced, i.e. does not require an ACK by the EC, the packet is completed 189 + with success on the transmitter thread. 190 + 191 + Transmission of sequenced packets is limited by the number of concurrently 192 + pending packets, i.e. a limit on how many packets may be waiting for an ACK 193 + from the EC in parallel. This limit is currently set to one (see :doc:`ssh` 194 + for the reasoning behind this). Control packets (i.e. ACK and NAK) can 195 + always be transmitted. 196 + 197 + Receiver Thread 198 + --------------- 199 + 200 + Any data received from the EC is put into a FIFO buffer for further 201 + processing. This processing happens on the receiver thread. The receiver 202 + thread parses and validates the received message into its |ssh_frame| and 203 + corresponding payload. It prepares and submits the necessary ACK (and on 204 + validation error or invalid data NAK) packets for the received messages. 205 + 206 + This thread also handles further processing, such as matching ACK messages 207 + to the corresponding pending packet (via sequence ID) and completing it, as 208 + well as initiating re-submission of all currently pending packets on 209 + receival of a NAK message (re-submission in case of a NAK is similar to 210 + re-submission due to timeout, see below for more details on that). Note that 211 + the successful completion of a sequenced packet will always run on the 212 + receiver thread (whereas any failure-indicating completion will run on the 213 + process where the failure occurred). 214 + 215 + Any payload data is forwarded via a callback to the next upper layer, i.e. 216 + the request transport layer. 217 + 218 + Timeout Reaper 219 + -------------- 220 + 221 + The packet acknowledgment timeout is a per-packet timeout for sequenced 222 + packets, started when the respective packet begins (re-)transmission (i.e. 223 + this timeout is armed once per transmission attempt on the transmitter 224 + thread). It is used to trigger re-submission or, when the number of tries 225 + has been exceeded, cancellation of the packet in question. 226 + 227 + This timeout is handled via a dedicated reaper task, which is essentially a 228 + work item (re-)scheduled to run when the next packet is set to time out. The 229 + work item then checks the set of pending packets for any packets that have 230 + exceeded the timeout and, if there are any remaining packets, re-schedules 231 + itself to the next appropriate point in time. 232 + 233 + If a timeout has been detected by the reaper, the packet will either be 234 + re-submitted if it still has some remaining tries left, or completed with 235 + ``-ETIMEDOUT`` as status if not. Note that re-submission, in this case and 236 + triggered by receival of a NAK, means that the packet is added to the queue 237 + with a now incremented number of tries, yielding a higher priority. The 238 + timeout for the packet will be disabled until the next transmission attempt 239 + and the packet remains on the pending set. 240 + 241 + Note that due to transmission and packet acknowledgment timeouts, the packet 242 + transport layer is always guaranteed to make progress, if only through 243 + timing out packets, and will never fully block. 244 + 245 + Concurrency and Locking 246 + ----------------------- 247 + 248 + There are two main locks in the packet transport layer: One guarding access 249 + to the packet queue and one guarding access to the pending set. These 250 + collections may only be accessed and modified under the respective lock. If 251 + access to both collections is needed, the pending lock must be acquired 252 + before the queue lock to avoid deadlocks. 253 + 254 + In addition to guarding the collections, after initial packet submission 255 + certain packet fields may only be accessed under one of the locks. 256 + Specifically, the packet priority must only be accessed while holding the 257 + queue lock and the packet timestamp must only be accessed while holding the 258 + pending lock. 259 + 260 + Other parts of the packet transport layer are guarded independently. State 261 + flags are managed by atomic bit operations and, if necessary, memory 262 + barriers. Modifications to the timeout reaper work item and expiration date 263 + are guarded by their own lock. 264 + 265 + The reference of the packet to the packet transport layer (``ptl``) is 266 + somewhat special. It is either set when the upper layer request is submitted 267 + or, if there is none, when the packet is first submitted. After it is set, 268 + it will not change its value. Functions that may run concurrently with 269 + submission, i.e. cancellation, can not rely on the ``ptl`` reference to be 270 + set. Access to it in these functions is guarded by ``READ_ONCE()``, whereas 271 + setting ``ptl`` is equally guarded with ``WRITE_ONCE()`` for symmetry. 272 + 273 + Some packet fields may be read outside of the respective locks guarding 274 + them, specifically priority and state for tracing. In those cases, proper 275 + access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such 276 + read-only access is only allowed when stale values are not critical. 277 + 278 + With respect to the interface for higher layers, packet submission 279 + (|ssh_ptl_submit|), packet cancellation (|ssh_ptl_cancel|), data receival 280 + (|ssh_ptl_rx_rcvbuf|), and layer shutdown (|ssh_ptl_shutdown|) may always be 281 + executed concurrently with respect to each other. Note that packet 282 + submission may not run concurrently with itself for the same packet. 283 + Equally, shutdown and data receival may also not run concurrently with 284 + themselves (but may run concurrently with each other). 285 + 286 + 287 + Request Transport Layer 288 + ======================= 289 + 290 + The request transport layer is represented via |ssh_rtl| and builds on top 291 + of the packet transport layer. It deals with requests, i.e. SSH packets sent 292 + by the host containing a |ssh_command| as frame payload. This layer 293 + separates responses to requests from events, which are also sent by the EC 294 + via a |ssh_command| payload. While responses are handled in this layer, 295 + events are relayed to the next upper layer, i.e. the controller layer, via 296 + the corresponding callback. The request transport layer is structured around 297 + the following key concepts: 298 + 299 + Request 300 + ------- 301 + 302 + Requests are packets with a command-type payload, sent from host to EC to 303 + query data from or trigger an action on it (or both simultaneously). They 304 + are represented by |ssh_request|, wrapping the underlying |ssh_packet| 305 + storing its message data (i.e. SSH frame with command payload). Note that 306 + all top-level representations, e.g. |ssam_request_sync| are built upon this 307 + struct. 308 + 309 + As |ssh_request| extends |ssh_packet|, its lifetime is also managed by the 310 + reference counter inside the packet struct (which can be accessed via 311 + |ssh_request_get| and |ssh_request_put|). Once the counter reaches zero, the 312 + ``release()`` callback of the |ssh_request_ops| reference of the request is 313 + called. 314 + 315 + Requests can have an optional response that is equally sent via a SSH 316 + message with command-type payload (from EC to host). The party constructing 317 + the request must know if a response is expected and mark this in the request 318 + flags provided to |ssh_request_init|, so that the request transport layer 319 + can wait for this response. 320 + 321 + Similar to |ssh_packet|, |ssh_request| also has a ``complete()`` callback 322 + provided via its request ops reference and is guaranteed to be completed 323 + before it is released once it has been submitted to the request transport 324 + layer via |ssh_rtl_submit|. For a request without a response, successful 325 + completion will occur once the underlying packet has been successfully 326 + transmitted by the packet transport layer (i.e. from within the packet 327 + completion callback). For a request with response, successful completion 328 + will occur once the response has been received and matched to the request 329 + via its request ID (which happens on the packet layer's data-received 330 + callback running on the receiver thread). If the request is completed with 331 + an error, the status value will be set to the corresponding (negative) errno 332 + value. 333 + 334 + The state of a request is again managed via its ``state`` flags 335 + (|ssh_request_flags|), which also encode the request type. In particular, 336 + the following bits are noteworthy: 337 + 338 + * ``SSH_REQUEST_SF_LOCKED_BIT``: This bit is set when completion, either 339 + through error or success, is imminent. It indicates that no further 340 + references of the request should be taken and any existing references 341 + should be dropped as soon as possible. The process setting this bit is 342 + responsible for removing any references to this request from the request 343 + queue and pending set. 344 + 345 + * ``SSH_REQUEST_SF_COMPLETED_BIT``: This bit is set by the process running the 346 + ``complete()`` callback and is used to ensure that this callback only runs 347 + once. 348 + 349 + * ``SSH_REQUEST_SF_QUEUED_BIT``: This bit is set when the request is queued on 350 + the request queue and cleared when it is dequeued. 351 + 352 + * ``SSH_REQUEST_SF_PENDING_BIT``: This bit is set when the request is added to 353 + the pending set and cleared when it is removed from it. 354 + 355 + Request Queue 356 + ------------- 357 + 358 + The request queue is the first of the two fundamental collections in the 359 + request transport layer. In contrast to the packet queue of the packet 360 + transport layer, it is not a priority queue and the simple first come first 361 + serve principle applies. 362 + 363 + All requests to be transmitted by the request transport layer must be 364 + submitted to this queue via |ssh_rtl_submit|. Once submitted, requests may 365 + not be re-submitted, and will not be re-submitted automatically on timeout. 366 + Instead, the request is completed with a timeout error. If desired, the 367 + caller can create and submit a new request for another try, but it must not 368 + submit the same request again. 369 + 370 + Pending Set 371 + ----------- 372 + 373 + The pending set is the second of the two fundamental collections in the 374 + request transport layer. This collection stores references to all pending 375 + requests, i.e. requests awaiting a response from the EC (similar to what the 376 + pending set of the packet transport layer does for packets). 377 + 378 + Transmitter Task 379 + ---------------- 380 + 381 + The transmitter task is scheduled when a new request is available for 382 + transmission. It checks if the next request on the request queue can be 383 + transmitted and, if so, submits its underlying packet to the packet 384 + transport layer. This check ensures that only a limited number of 385 + requests can be pending, i.e. waiting for a response, at the same time. If 386 + the request requires a response, the request is added to the pending set 387 + before its packet is submitted. 388 + 389 + Packet Completion Callback 390 + -------------------------- 391 + 392 + The packet completion callback is executed once the underlying packet of a 393 + request has been completed. In case of an error completion, the 394 + corresponding request is completed with the error value provided in this 395 + callback. 396 + 397 + On successful packet completion, further processing depends on the request. 398 + If the request expects a response, it is marked as transmitted and the 399 + request timeout is started. If the request does not expect a response, it is 400 + completed with success. 401 + 402 + Data-Received Callback 403 + ---------------------- 404 + 405 + The data received callback notifies the request transport layer of data 406 + being received by the underlying packet transport layer via a data-type 407 + frame. In general, this is expected to be a command-type payload. 408 + 409 + If the request ID of the command is one of the request IDs reserved for 410 + events (one to ``SSH_NUM_EVENTS``, inclusively), it is forwarded to the 411 + event callback registered in the request transport layer. If the request ID 412 + indicates a response to a request, the respective request is looked up in 413 + the pending set and, if found and marked as transmitted, completed with 414 + success. 415 + 416 + Timeout Reaper 417 + -------------- 418 + 419 + The request-response-timeout is a per-request timeout for requests expecting 420 + a response. It is used to ensure that a request does not wait indefinitely 421 + on a response from the EC and is started after the underlying packet has 422 + been successfully completed. 423 + 424 + This timeout is, similar to the packet acknowledgment timeout on the packet 425 + transport layer, handled via a dedicated reaper task. This task is 426 + essentially a work-item (re-)scheduled to run when the next request is set 427 + to time out. The work item then scans the set of pending requests for any 428 + requests that have timed out and completes them with ``-ETIMEDOUT`` as 429 + status. Requests will not be re-submitted automatically. Instead, the issuer 430 + of the request must construct and submit a new request, if so desired. 431 + 432 + Note that this timeout, in combination with packet transmission and 433 + acknowledgment timeouts, guarantees that the request layer will always make 434 + progress, even if only through timing out packets, and never fully block. 435 + 436 + Concurrency and Locking 437 + ----------------------- 438 + 439 + Similar to the packet transport layer, there are two main locks in the 440 + request transport layer: One guarding access to the request queue and one 441 + guarding access to the pending set. These collections may only be accessed 442 + and modified under the respective lock. 443 + 444 + Other parts of the request transport layer are guarded independently. State 445 + flags are (again) managed by atomic bit operations and, if necessary, memory 446 + barriers. Modifications to the timeout reaper work item and expiration date 447 + are guarded by their own lock. 448 + 449 + Some request fields may be read outside of the respective locks guarding 450 + them, specifically the state for tracing. In those cases, proper access is 451 + ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such read-only 452 + access is only allowed when stale values are not critical. 453 + 454 + With respect to the interface for higher layers, request submission 455 + (|ssh_rtl_submit|), request cancellation (|ssh_rtl_cancel|), and layer 456 + shutdown (|ssh_rtl_shutdown|) may always be executed concurrently with 457 + respect to each other. Note that request submission may not run concurrently 458 + with itself for the same request (and also may only be called once per 459 + request). Equally, shutdown may also not run concurrently with itself. 460 + 461 + 462 + Controller Layer 463 + ================ 464 + 465 + The controller layer extends on the request transport layer to provide an 466 + easy-to-use interface for client drivers. It is represented by 467 + |ssam_controller| and the SSH driver. While the lower level transport layers 468 + take care of transmitting and handling packets and requests, the controller 469 + layer takes on more of a management role. Specifically, it handles device 470 + initialization, power management, and event handling, including event 471 + delivery and registration via the (event) completion system (|ssam_cplt|). 472 + 473 + Event Registration 474 + ------------------ 475 + 476 + In general, an event (or rather a class of events) has to be explicitly 477 + requested by the host before the EC will send it (HID input events seem to 478 + be the exception). This is done via an event-enable request (similarly, 479 + events should be disabled via an event-disable request once no longer 480 + desired). 481 + 482 + The specific request used to enable (or disable) an event is given via an 483 + event registry, i.e. the governing authority of this event (so to speak), 484 + represented by |ssam_event_registry|. As parameters to this request, the 485 + target category and, depending on the event registry, instance ID of the 486 + event to be enabled must be provided. This (optional) instance ID must be 487 + zero if the registry does not use it. Together, target category and instance 488 + ID form the event ID, represented by |ssam_event_id|. In short, both, event 489 + registry and event ID, are required to uniquely identify a respective class 490 + of events. 491 + 492 + Note that a further *request ID* parameter must be provided for the 493 + enable-event request. This parameter does not influence the class of events 494 + being enabled, but instead is set as the request ID (RQID) on each event of 495 + this class sent by the EC. It is used to identify events (as a limited 496 + number of request IDs is reserved for use in events only, specifically one 497 + to ``SSH_NUM_EVENTS`` inclusively) and also map events to their specific 498 + class. Currently, the controller always sets this parameter to the target 499 + category specified in |ssam_event_id|. 500 + 501 + As multiple client drivers may rely on the same (or overlapping) classes of 502 + events and enable/disable calls are strictly binary (i.e. on/off), the 503 + controller has to manage access to these events. It does so via reference 504 + counting, storing the counter inside an RB-tree based mapping with event 505 + registry and ID as key (there is no known list of valid event registry and 506 + event ID combinations). See |ssam_nf|, |ssam_nf_refcount_inc|, and 507 + |ssam_nf_refcount_dec| for details. 508 + 509 + This management is done together with notifier registration (described in 510 + the next section) via the top-level |ssam_notifier_register| and 511 + |ssam_notifier_unregister| functions. 512 + 513 + Event Delivery 514 + -------------- 515 + 516 + To receive events, a client driver has to register an event notifier via 517 + |ssam_notifier_register|. This increments the reference counter for that 518 + specific class of events (as detailed in the previous section), enables the 519 + class on the EC (if it has not been enabled already), and installs the 520 + provided notifier callback. 521 + 522 + Notifier callbacks are stored in lists, with one (RCU) list per target 523 + category (provided via the event ID; NB: there is a fixed known number of 524 + target categories). There is no known association from the combination of 525 + event registry and event ID to the command data (target ID, target category, 526 + command ID, and instance ID) that can be provided by an event class, apart 527 + from target category and instance ID given via the event ID. 528 + 529 + Note that due to the way notifiers are (or rather have to be) stored, client 530 + drivers may receive events that they have not requested and need to account 531 + for them. Specifically, they will, by default, receive all events from the 532 + same target category. To simplify dealing with this, filtering of events by 533 + target ID (provided via the event registry) and instance ID (provided via 534 + the event ID) can be requested when registering a notifier. This filtering 535 + is applied when iterating over the notifiers at the time they are executed. 536 + 537 + All notifier callbacks are executed on a dedicated workqueue, the so-called 538 + completion workqueue. After an event has been received via the callback 539 + installed in the request layer (running on the receiver thread of the packet 540 + transport layer), it will be put on its respective event queue 541 + (|ssam_event_queue|). From this event queue the completion work item of that 542 + queue (running on the completion workqueue) will pick up the event and 543 + execute the notifier callback. This is done to avoid blocking on the 544 + receiver thread. 545 + 546 + There is one event queue per combination of target ID and target category. 547 + This is done to ensure that notifier callbacks are executed in sequence for 548 + events of the same target ID and target category. Callbacks can be executed 549 + in parallel for events with a different combination of target ID and target 550 + category. 551 + 552 + Concurrency and Locking 553 + ----------------------- 554 + 555 + Most of the concurrency related safety guarantees of the controller are 556 + provided by the lower-level request transport layer. In addition to this, 557 + event (un-)registration is guarded by its own lock. 558 + 559 + Access to the controller state is guarded by the state lock. This lock is a 560 + read/write semaphore. The reader part can be used to ensure that the state 561 + does not change while functions depending on the state to stay the same 562 + (e.g. |ssam_notifier_register|, |ssam_notifier_unregister|, 563 + |ssam_request_sync_submit|, and derivatives) are executed and this guarantee 564 + is not already provided otherwise (e.g. through |ssam_client_bind| or 565 + |ssam_client_link|). The writer part guards any transitions that will change 566 + the state, i.e. initialization, destruction, suspension, and resumption. 567 + 568 + The controller state may be accessed (read-only) outside the state lock for 569 + smoke-testing against invalid API usage (e.g. in |ssam_request_sync_submit|). 570 + Note that such checks are not supposed to (and will not) protect against all 571 + invalid usages, but rather aim to help catch them. In those cases, proper 572 + variable access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. 573 + 574 + Assuming any preconditions on the state not changing have been satisfied, 575 + all non-initialization and non-shutdown functions may run concurrently with 576 + each other. This includes |ssam_notifier_register|, |ssam_notifier_unregister|, 577 + |ssam_request_sync_submit|, as well as all functions building on top of those.
+77
Documentation/driver-api/surface_aggregator/overview.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + ======== 4 + Overview 5 + ======== 6 + 7 + The Surface/System Aggregator Module (SAM, SSAM) is an (arguably *the*) 8 + embedded controller (EC) on Microsoft Surface devices. It has been originally 9 + introduced on 4th generation devices (Surface Pro 4, Surface Book 1), but 10 + its responsibilities and feature-set have since been expanded significantly 11 + with the following generations. 12 + 13 + 14 + Features and Integration 15 + ======================== 16 + 17 + Not much is currently known about SAM on 4th generation devices (Surface Pro 18 + 4, Surface Book 1), due to the use of a different communication interface 19 + between host and EC (as detailed below). On 5th (Surface Pro 2017, Surface 20 + Book 2, Surface Laptop 1) and later generation devices, SAM is responsible 21 + for providing battery information (both current status and static values, 22 + such as maximum capacity etc.), as well as an assortment of temperature 23 + sensors (e.g. skin temperature) and cooling/performance-mode setting to the 24 + host. On the Surface Book 2, specifically, it additionally provides an 25 + interface for properly handling clipboard detachment (i.e. separating the 26 + display part from the keyboard part of the device), on the Surface Laptop 1 27 + and 2 it is required for keyboard HID input. This HID subsystem has been 28 + restructured for 7th generation devices and on those, specifically Surface 29 + Laptop 3 and Surface Book 3, is responsible for all major HID input (i.e. 30 + keyboard and touchpad). 31 + 32 + While features have not changed much on a coarse level since the 5th 33 + generation, internal interfaces have undergone some rather large changes. On 34 + 5th and 6th generation devices, both battery and temperature information is 35 + exposed to ACPI via a shim driver (referred to as Surface ACPI Notify, or 36 + SAN), translating ACPI generic serial bus write-/read-accesses to SAM 37 + requests. On 7th generation devices, this additional layer is gone and these 38 + devices require a driver hooking directly into the SAM interface. Equally, 39 + on newer generations, less devices are declared in ACPI, making them a bit 40 + harder to discover and requiring us to hard-code a sort of device registry. 41 + Due to this, a SSAM bus and subsystem with client devices 42 + (:c:type:`struct ssam_device <ssam_device>`) has been implemented. 43 + 44 + 45 + Communication 46 + ============= 47 + 48 + The type of communication interface between host and EC depends on the 49 + generation of the Surface device. On 4th generation devices, host and EC 50 + communicate via HID, specifically using a HID-over-I2C device, whereas on 51 + 5th and later generations, communication takes place via a USART serial 52 + device. In accordance to the drivers found on other operating systems, we 53 + refer to the serial device and its driver as Surface Serial Hub (SSH). When 54 + needed, we differentiate between both types of SAM by referring to them as 55 + SAM-over-SSH and SAM-over-HID. 56 + 57 + Currently, this subsystem only supports SAM-over-SSH. The SSH communication 58 + interface is described in more detail below. The HID interface has not been 59 + reverse engineered yet and it is, at the moment, unclear how many (and 60 + which) concepts of the SSH interface detailed below can be transferred to 61 + it. 62 + 63 + Surface Serial Hub 64 + ------------------ 65 + 66 + As already elaborated above, the Surface Serial Hub (SSH) is the 67 + communication interface for SAM on 5th- and all later-generation Surface 68 + devices. On the highest level, communication can be separated into two main 69 + types: Requests, messages sent from host to EC that may trigger a direct 70 + response from the EC (explicitly associated with the request), and events 71 + (sometimes also referred to as notifications), sent from EC to host without 72 + being a direct response to a previous request. We may also refer to requests 73 + without response as commands. In general, events need to be enabled via one 74 + of multiple dedicated requests before they are sent by the EC. 75 + 76 + See :doc:`ssh` for a more technical protocol documentation and 77 + :doc:`internal` for an overview of the internal driver architecture.
+344
Documentation/driver-api/surface_aggregator/ssh.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + .. |u8| replace:: :c:type:`u8 <u8>` 4 + .. |u16| replace:: :c:type:`u16 <u16>` 5 + .. |TYPE| replace:: ``TYPE`` 6 + .. |LEN| replace:: ``LEN`` 7 + .. |SEQ| replace:: ``SEQ`` 8 + .. |SYN| replace:: ``SYN`` 9 + .. |NAK| replace:: ``NAK`` 10 + .. |ACK| replace:: ``ACK`` 11 + .. |DATA| replace:: ``DATA`` 12 + .. |DATA_SEQ| replace:: ``DATA_SEQ`` 13 + .. |DATA_NSQ| replace:: ``DATA_NSQ`` 14 + .. |TC| replace:: ``TC`` 15 + .. |TID| replace:: ``TID`` 16 + .. |IID| replace:: ``IID`` 17 + .. |RQID| replace:: ``RQID`` 18 + .. |CID| replace:: ``CID`` 19 + 20 + =========================== 21 + Surface Serial Hub Protocol 22 + =========================== 23 + 24 + The Surface Serial Hub (SSH) is the central communication interface for the 25 + embedded Surface Aggregator Module controller (SAM or EC), found on newer 26 + Surface generations. We will refer to this protocol and interface as 27 + SAM-over-SSH, as opposed to SAM-over-HID for the older generations. 28 + 29 + On Surface devices with SAM-over-SSH, SAM is connected to the host via UART 30 + and defined in ACPI as device with ID ``MSHW0084``. On these devices, 31 + significant functionality is provided via SAM, including access to battery 32 + and power information and events, thermal read-outs and events, and many 33 + more. For Surface Laptops, keyboard input is handled via HID directed 34 + through SAM, on the Surface Laptop 3 and Surface Book 3 this also includes 35 + touchpad input. 36 + 37 + Note that the standard disclaimer for this subsystem also applies to this 38 + document: All of this has been reverse-engineered and may thus be erroneous 39 + and/or incomplete. 40 + 41 + All CRCs used in the following are two-byte ``crc_ccitt_false(0xffff, ...)``. 42 + All multi-byte values are little-endian, there is no implicit padding between 43 + values. 44 + 45 + 46 + SSH Packet Protocol: Definitions 47 + ================================ 48 + 49 + The fundamental communication unit of the SSH protocol is a frame 50 + (:c:type:`struct ssh_frame <ssh_frame>`). A frame consists of the following 51 + fields, packed together and in order: 52 + 53 + .. flat-table:: SSH Frame 54 + :widths: 1 1 4 55 + :header-rows: 1 56 + 57 + * - Field 58 + - Type 59 + - Description 60 + 61 + * - |TYPE| 62 + - |u8| 63 + - Type identifier of the frame. 64 + 65 + * - |LEN| 66 + - |u16| 67 + - Length of the payload associated with the frame. 68 + 69 + * - |SEQ| 70 + - |u8| 71 + - Sequence ID (see explanation below). 72 + 73 + Each frame structure is followed by a CRC over this structure. The CRC over 74 + the frame structure (|TYPE|, |LEN|, and |SEQ| fields) is placed directly 75 + after the frame structure and before the payload. The payload is followed by 76 + its own CRC (over all payload bytes). If the payload is not present (i.e. 77 + the frame has ``LEN=0``), the CRC of the payload is still present and will 78 + evaluate to ``0xffff``. The |LEN| field does not include any of the CRCs, it 79 + equals the number of bytes inbetween the CRC of the frame and the CRC of the 80 + payload. 81 + 82 + Additionally, the following fixed two-byte sequences are used: 83 + 84 + .. flat-table:: SSH Byte Sequences 85 + :widths: 1 1 4 86 + :header-rows: 1 87 + 88 + * - Name 89 + - Value 90 + - Description 91 + 92 + * - |SYN| 93 + - ``[0xAA, 0x55]`` 94 + - Synchronization bytes. 95 + 96 + A message consists of |SYN|, followed by the frame (|TYPE|, |LEN|, |SEQ| and 97 + CRC) and, if specified in the frame (i.e. ``LEN > 0``), payload bytes, 98 + followed finally, regardless if the payload is present, the payload CRC. The 99 + messages corresponding to an exchange are, in part, identified by having the 100 + same sequence ID (|SEQ|), stored inside the frame (more on this in the next 101 + section). The sequence ID is a wrapping counter. 102 + 103 + A frame can have the following types 104 + (:c:type:`enum ssh_frame_type <ssh_frame_type>`): 105 + 106 + .. flat-table:: SSH Frame Types 107 + :widths: 1 1 4 108 + :header-rows: 1 109 + 110 + * - Name 111 + - Value 112 + - Short Description 113 + 114 + * - |NAK| 115 + - ``0x04`` 116 + - Sent on error in previously received message. 117 + 118 + * - |ACK| 119 + - ``0x40`` 120 + - Sent to acknowledge receival of |DATA| frame. 121 + 122 + * - |DATA_SEQ| 123 + - ``0x80`` 124 + - Sent to transfer data. Sequenced. 125 + 126 + * - |DATA_NSQ| 127 + - ``0x00`` 128 + - Same as |DATA_SEQ|, but does not need to be ACKed. 129 + 130 + Both |NAK|- and |ACK|-type frames are used to control flow of messages and 131 + thus do not carry a payload. |DATA_SEQ|- and |DATA_NSQ|-type frames on the 132 + other hand must carry a payload. The flow sequence and interaction of 133 + different frame types will be described in more depth in the next section. 134 + 135 + 136 + SSH Packet Protocol: Flow Sequence 137 + ================================== 138 + 139 + Each exchange begins with |SYN|, followed by a |DATA_SEQ|- or 140 + |DATA_NSQ|-type frame, followed by its CRC, payload, and payload CRC. In 141 + case of a |DATA_NSQ|-type frame, the exchange is then finished. In case of a 142 + |DATA_SEQ|-type frame, the receiving party has to acknowledge receival of 143 + the frame by responding with a message containing an |ACK|-type frame with 144 + the same sequence ID of the |DATA| frame. In other words, the sequence ID of 145 + the |ACK| frame specifies the |DATA| frame to be acknowledged. In case of an 146 + error, e.g. an invalid CRC, the receiving party responds with a message 147 + containing an |NAK|-type frame. As the sequence ID of the previous data 148 + frame, for which an error is indicated via the |NAK| frame, cannot be relied 149 + upon, the sequence ID of the |NAK| frame should not be used and is set to 150 + zero. After receival of an |NAK| frame, the sending party should re-send all 151 + outstanding (non-ACKed) messages. 152 + 153 + Sequence IDs are not synchronized between the two parties, meaning that they 154 + are managed independently for each party. Identifying the messages 155 + corresponding to a single exchange thus relies on the sequence ID as well as 156 + the type of the message, and the context. Specifically, the sequence ID is 157 + used to associate an ``ACK`` with its ``DATA_SEQ``-type frame, but not 158 + ``DATA_SEQ``- or ``DATA_NSQ``-type frames with other ``DATA``- type frames. 159 + 160 + An example exchange might look like this: 161 + 162 + :: 163 + 164 + tx: -- SYN FRAME(D) CRC(F) PAYLOAD CRC(P) ----------------------------- 165 + rx: ------------------------------------- SYN FRAME(A) CRC(F) CRC(P) -- 166 + 167 + where both frames have the same sequence ID (``SEQ``). Here, ``FRAME(D)`` 168 + indicates a |DATA_SEQ|-type frame, ``FRAME(A)`` an ``ACK``-type frame, 169 + ``CRC(F)`` the CRC over the previous frame, ``CRC(P)`` the CRC over the 170 + previous payload. In case of an error, the exchange would look like this: 171 + 172 + :: 173 + 174 + tx: -- SYN FRAME(D) CRC(F) PAYLOAD CRC(P) ----------------------------- 175 + rx: ------------------------------------- SYN FRAME(N) CRC(F) CRC(P) -- 176 + 177 + upon which the sender should re-send the message. ``FRAME(N)`` indicates an 178 + |NAK|-type frame. Note that the sequence ID of the |NAK|-type frame is fixed 179 + to zero. For |DATA_NSQ|-type frames, both exchanges are the same: 180 + 181 + :: 182 + 183 + tx: -- SYN FRAME(DATA_NSQ) CRC(F) PAYLOAD CRC(P) ---------------------- 184 + rx: ------------------------------------------------------------------- 185 + 186 + Here, an error can be detected, but not corrected or indicated to the 187 + sending party. These exchanges are symmetric, i.e. switching ``rx`` and 188 + ``tx`` results again in a valid exchange. Currently, no longer exchanges are 189 + known. 190 + 191 + 192 + Commands: Requests, Responses, and Events 193 + ========================================= 194 + 195 + Commands are sent as payload inside a data frame. Currently, this is the 196 + only known payload type of |DATA| frames, with a payload-type value of 197 + ``0x80`` (:c:type:`SSH_PLD_TYPE_CMD <ssh_payload_type>`). 198 + 199 + The command-type payload (:c:type:`struct ssh_command <ssh_command>`) 200 + consists of an eight-byte command structure, followed by optional and 201 + variable length command data. The length of this optional data is derived 202 + from the frame payload length given in the corresponding frame, i.e. it is 203 + ``frame.len - sizeof(struct ssh_command)``. The command struct contains the 204 + following fields, packed together and in order: 205 + 206 + .. flat-table:: SSH Command 207 + :widths: 1 1 4 208 + :header-rows: 1 209 + 210 + * - Field 211 + - Type 212 + - Description 213 + 214 + * - |TYPE| 215 + - |u8| 216 + - Type of the payload. For commands always ``0x80``. 217 + 218 + * - |TC| 219 + - |u8| 220 + - Target category. 221 + 222 + * - |TID| (out) 223 + - |u8| 224 + - Target ID for outgoing (host to EC) commands. 225 + 226 + * - |TID| (in) 227 + - |u8| 228 + - Target ID for incoming (EC to host) commands. 229 + 230 + * - |IID| 231 + - |u8| 232 + - Instance ID. 233 + 234 + * - |RQID| 235 + - |u16| 236 + - Request ID. 237 + 238 + * - |CID| 239 + - |u8| 240 + - Command ID. 241 + 242 + The command struct and data, in general, does not contain any failure 243 + detection mechanism (e.g. CRCs), this is solely done on the frame level. 244 + 245 + Command-type payloads are used by the host to send commands and requests to 246 + the EC as well as by the EC to send responses and events back to the host. 247 + We differentiate between requests (sent by the host), responses (sent by the 248 + EC in response to a request), and events (sent by the EC without a preceding 249 + request). 250 + 251 + Commands and events are uniquely identified by their target category 252 + (``TC``) and command ID (``CID``). The target category specifies a general 253 + category for the command (e.g. system in general, vs. battery and AC, vs. 254 + temperature, and so on), while the command ID specifies the command inside 255 + that category. Only the combination of |TC| + |CID| is unique. Additionally, 256 + commands have an instance ID (``IID``), which is used to differentiate 257 + between different sub-devices. For example ``TC=3`` ``CID=1`` is a 258 + request to get the temperature on a thermal sensor, where |IID| specifies 259 + the respective sensor. If the instance ID is not used, it should be set to 260 + zero. If instance IDs are used, they, in general, start with a value of one, 261 + whereas zero may be used for instance independent queries, if applicable. A 262 + response to a request should have the same target category, command ID, and 263 + instance ID as the corresponding request. 264 + 265 + Responses are matched to their corresponding request via the request ID 266 + (``RQID``) field. This is a 16 bit wrapping counter similar to the sequence 267 + ID on the frames. Note that the sequence ID of the frames for a 268 + request-response pair does not match. Only the request ID has to match. 269 + Frame-protocol wise these are two separate exchanges, and may even be 270 + separated, e.g. by an event being sent after the request but before the 271 + response. Not all commands produce a response, and this is not detectable by 272 + |TC| + |CID|. It is the responsibility of the issuing party to wait for a 273 + response (or signal this to the communication framework, as is done in 274 + SAN/ACPI via the ``SNC`` flag). 275 + 276 + Events are identified by unique and reserved request IDs. These IDs should 277 + not be used by the host when sending a new request. They are used on the 278 + host to, first, detect events and, second, match them with a registered 279 + event handler. Request IDs for events are chosen by the host and directed to 280 + the EC when setting up and enabling an event source (via the 281 + enable-event-source request). The EC then uses the specified request ID for 282 + events sent from the respective source. Note that an event should still be 283 + identified by its target category, command ID, and, if applicable, instance 284 + ID, as a single event source can send multiple different event types. In 285 + general, however, a single target category should map to a single reserved 286 + event request ID. 287 + 288 + Furthermore, requests, responses, and events have an associated target ID 289 + (``TID``). This target ID is split into output (host to EC) and input (EC to 290 + host) fields, with the respecting other field (e.g. output field on incoming 291 + messages) set to zero. Two ``TID`` values are known: Primary (``0x01``) and 292 + secondary (``0x02``). In general, the response to a request should have the 293 + same ``TID`` value, however, the field (output vs. input) should be used in 294 + accordance to the direction in which the response is sent (i.e. on the input 295 + field, as responses are generally sent from the EC to the host). 296 + 297 + Note that, even though requests and events should be uniquely identifiable 298 + by target category and command ID alone, the EC may require specific 299 + target ID and instance ID values to accept a command. A command that is 300 + accepted for ``TID=1``, for example, may not be accepted for ``TID=2`` 301 + and vice versa. 302 + 303 + 304 + Limitations and Observations 305 + ============================ 306 + 307 + The protocol can, in theory, handle up to ``U8_MAX`` frames in parallel, 308 + with up to ``U16_MAX`` pending requests (neglecting request IDs reserved for 309 + events). In practice, however, this is more limited. From our testing 310 + (although via a python and thus a user-space program), it seems that the EC 311 + can handle up to four requests (mostly) reliably in parallel at a certain 312 + time. With five or more requests in parallel, consistent discarding of 313 + commands (ACKed frame but no command response) has been observed. For five 314 + simultaneous commands, this reproducibly resulted in one command being 315 + dropped and four commands being handled. 316 + 317 + However, it has also been noted that, even with three requests in parallel, 318 + occasional frame drops happen. Apart from this, with a limit of three 319 + pending requests, no dropped commands (i.e. command being dropped but frame 320 + carrying command being ACKed) have been observed. In any case, frames (and 321 + possibly also commands) should be re-sent by the host if a certain timeout 322 + is exceeded. This is done by the EC for frames with a timeout of one second, 323 + up to two re-tries (i.e. three transmissions in total). The limit of 324 + re-tries also applies to received NAKs, and, in a worst case scenario, can 325 + lead to entire messages being dropped. 326 + 327 + While this also seems to work fine for pending data frames as long as no 328 + transmission failures occur, implementation and handling of these seems to 329 + depend on the assumption that there is only one non-acknowledged data frame. 330 + In particular, the detection of repeated frames relies on the last sequence 331 + number. This means that, if a frame that has been successfully received by 332 + the EC is sent again, e.g. due to the host not receiving an |ACK|, the EC 333 + will only detect this if it has the sequence ID of the last frame received 334 + by the EC. As an example: Sending two frames with ``SEQ=0`` and ``SEQ=1`` 335 + followed by a repetition of ``SEQ=0`` will not detect the second ``SEQ=0`` 336 + frame as such, and thus execute the command in this frame each time it has 337 + been received, i.e. twice in this example. Sending ``SEQ=0``, ``SEQ=1`` and 338 + then repeating ``SEQ=1`` will detect the second ``SEQ=1`` as repetition of 339 + the first one and ignore it, thus executing the contained command only once. 340 + 341 + In conclusion, this suggests a limit of at most one pending un-ACKed frame 342 + (per party, effectively leading to synchronous communication regarding 343 + frames) and at most three pending commands. The limit to synchronous frame 344 + transfers seems to be consistent with behavior observed on Windows.
+1
MAINTAINERS
··· 11818 11818 S: Maintained 11819 11819 W: https://github.com/linux-surface/surface-aggregator-module 11820 11820 C: irc://chat.freenode.net/##linux-surface 11821 + F: Documentation/driver-api/surface_aggregator/ 11821 11822 F: drivers/platform/surface/aggregator/ 11822 11823 F: include/linux/surface_aggregator/ 11823 11824