€•Œsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ:/translations/zh_CN/driver-api/surface_aggregator/internal”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ:/translations/zh_TW/driver-api/surface_aggregator/internal”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ:/translations/it_IT/driver-api/surface_aggregator/internal”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ:/translations/ja_JP/driver-api/surface_aggregator/internal”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ:/translations/ko_KR/driver-api/surface_aggregator/internal”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ:/translations/pt_BR/driver-api/surface_aggregator/internal”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ:/translations/sp_SP/driver-api/surface_aggregator/internal”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)”}”(hŒ!SPDX-License-Identifier: GPL-2.0+”h]”hŒ!SPDX-License-Identifier: GPL-2.0+”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³ŒT/var/lib/git/docbuild/linux/Documentation/driver-api/surface_aggregator/internal.rst”h´KubhŒsubstitution_definition”“”)”}”(hŒ9.. |ssh_ptl| replace:: :c:type:`struct ssh_ptl `”h]”h)”}”(hŒ":c:type:`struct ssh_ptl `”h]”hŒliteral”“”)”}”(hhÐh]”hŒstruct ssh_ptl”…””}”(hhÔh²hh³Nh´Nubah}”(h]”h ]”(Œxref”Œc”Œc-type”eh"]”h$]”h&]”uh1hÒhhÎubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”Œ&driver-api/surface_aggregator/internal”Œ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰Œ reftarget”Œssh_ptl”uh1hh³hÇh´KhhÊubah}”(h]”h ]”h"]”Œssh_ptl”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ6.. |ssh_ptl_submit| replace:: :c:func:`ssh_ptl_submit`”h]”h)”}”(hŒ:c:func:`ssh_ptl_submit`”h]”hÓ)”}”(hjh]”hŒssh_ptl_submit()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhhþubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_ptl_submit”uh1hh³hÇh´Khhúubah}”(h]”h ]”h"]”Œssh_ptl_submit”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ6.. |ssh_ptl_cancel| replace:: :c:func:`ssh_ptl_cancel`”h]”h)”}”(hŒ:c:func:`ssh_ptl_cancel`”h]”hÓ)”}”(hj*h]”hŒssh_ptl_cancel()”…””}”(hj,h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhj(ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_ptl_cancel”uh1hh³hÇh´Khj$ubah}”(h]”h ]”h"]”Œssh_ptl_cancel”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ:.. |ssh_ptl_shutdown| replace:: :c:func:`ssh_ptl_shutdown`”h]”h)”}”(hŒ:c:func:`ssh_ptl_shutdown`”h]”hÓ)”}”(hjTh]”hŒssh_ptl_shutdown()”…””}”(hjVh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjRubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_ptl_shutdown”uh1hh³hÇh´KhjNubah}”(h]”h ]”h"]”Œssh_ptl_shutdown”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ<.. |ssh_ptl_rx_rcvbuf| replace:: :c:func:`ssh_ptl_rx_rcvbuf`”h]”h)”}”(hŒ:c:func:`ssh_ptl_rx_rcvbuf`”h]”hÓ)”}”(hj~h]”hŒssh_ptl_rx_rcvbuf()”…””}”(hj€h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhj|ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_ptl_rx_rcvbuf”uh1hh³hÇh´Khjxubah}”(h]”h ]”h"]”Œssh_ptl_rx_rcvbuf”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ9.. |ssh_rtl| replace:: :c:type:`struct ssh_rtl `”h]”h)”}”(hŒ":c:type:`struct ssh_rtl `”h]”hÓ)”}”(hj¨h]”hŒstruct ssh_rtl”…””}”(hjªh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhj¦ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssh_rtl”uh1hh³hÇh´Khj¢ubah}”(h]”h ]”h"]”Œssh_rtl”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ6.. |ssh_rtl_submit| replace:: :c:func:`ssh_rtl_submit`”h]”h)”}”(hŒ:c:func:`ssh_rtl_submit`”h]”hÓ)”}”(hjÒh]”hŒssh_rtl_submit()”…””}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjÐubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_rtl_submit”uh1hh³hÇh´K hjÌubah}”(h]”h ]”h"]”Œssh_rtl_submit”ah$]”h&]”uh1hÈh³hÇh´K hhh²hubhÉ)”}”(hŒ6.. |ssh_rtl_cancel| replace:: :c:func:`ssh_rtl_cancel`”h]”h)”}”(hŒ:c:func:`ssh_rtl_cancel`”h]”hÓ)”}”(hjüh]”hŒssh_rtl_cancel()”…””}”(hjþh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjúubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_rtl_cancel”uh1hh³hÇh´K hjöubah}”(h]”h ]”h"]”Œssh_rtl_cancel”ah$]”h&]”uh1hÈh³hÇh´K hhh²hubhÉ)”}”(hŒ:.. |ssh_rtl_shutdown| replace:: :c:func:`ssh_rtl_shutdown`”h]”h)”}”(hŒ:c:func:`ssh_rtl_shutdown`”h]”hÓ)”}”(hj&h]”hŒssh_rtl_shutdown()”…””}”(hj(h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhj$ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_rtl_shutdown”uh1hh³hÇh´K hj ubah}”(h]”h ]”h"]”Œssh_rtl_shutdown”ah$]”h&]”uh1hÈh³hÇh´K hhh²hubhÉ)”}”(hŒB.. |ssh_packet| replace:: :c:type:`struct ssh_packet `”h]”h)”}”(hŒ(:c:type:`struct ssh_packet `”h]”hÓ)”}”(hjPh]”hŒstruct ssh_packet”…””}”(hjRh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjNubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒ ssh_packet”uh1hh³hÇh´K hjJubah}”(h]”h ]”h"]”Œ ssh_packet”ah$]”h&]”uh1hÈh³hÇh´K hhh²hubhÉ)”}”(hŒ6.. |ssh_packet_get| replace:: :c:func:`ssh_packet_get`”h]”h)”}”(hŒ:c:func:`ssh_packet_get`”h]”hÓ)”}”(hjzh]”hŒssh_packet_get()”…””}”(hj|h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjxubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_packet_get”uh1hh³hÇh´K hjtubah}”(h]”h ]”h"]”Œssh_packet_get”ah$]”h&]”uh1hÈh³hÇh´K hhh²hubhÉ)”}”(hŒ6.. |ssh_packet_put| replace:: :c:func:`ssh_packet_put`”h]”h)”}”(hŒ:c:func:`ssh_packet_put`”h]”hÓ)”}”(hj¤h]”hŒssh_packet_put()”…””}”(hj¦h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhj¢ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_packet_put”uh1hh³hÇh´Khjžubah}”(h]”h ]”h"]”Œssh_packet_put”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒN.. |ssh_packet_ops| replace:: :c:type:`struct ssh_packet_ops `”h]”h)”}”(hŒ0:c:type:`struct ssh_packet_ops `”h]”hÓ)”}”(hjÎh]”hŒstruct ssh_packet_ops”…””}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjÌubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssh_packet_ops”uh1hh³hÇh´KhjÈubah}”(h]”h ]”h"]”Œssh_packet_ops”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒj.. |ssh_packet_base_priority| replace:: :c:type:`enum ssh_packet_base_priority `”h]”h)”}”(hŒB:c:type:`enum ssh_packet_base_priority `”h]”hÓ)”}”(hjøh]”hŒenum ssh_packet_base_priority”…””}”(hjúh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjöubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssh_packet_base_priority”uh1hh³hÇh´Khjòubah}”(h]”h ]”h"]”Œssh_packet_base_priority”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒR.. |ssh_packet_flags| replace:: :c:type:`enum ssh_packet_flags `”h]”h)”}”(hŒ2:c:type:`enum ssh_packet_flags `”h]”hÓ)”}”(hj"h]”hŒenum ssh_packet_flags”…””}”(hj$h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhj ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssh_packet_flags”uh1hh³hÇh´Khjubah}”(h]”h ]”h"]”Œssh_packet_flags”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ@.. |SSH_PACKET_PRIORITY| replace:: :c:func:`SSH_PACKET_PRIORITY`”h]”h)”}”(hŒ:c:func:`SSH_PACKET_PRIORITY`”h]”hÓ)”}”(hjLh]”hŒSSH_PACKET_PRIORITY()”…””}”(hjNh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjJubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒSSH_PACKET_PRIORITY”uh1hh³hÇh´KhjFubah}”(h]”h ]”h"]”ŒSSH_PACKET_PRIORITY”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ?.. |ssh_frame| replace:: :c:type:`struct ssh_frame `”h]”h)”}”(hŒ&:c:type:`struct ssh_frame `”h]”hÓ)”}”(hjvh]”hŒstruct ssh_frame”…””}”(hjxh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjtubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒ ssh_frame”uh1hh³hÇh´Khjpubah}”(h]”h ]”h"]”Œ ssh_frame”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒE.. |ssh_command| replace:: :c:type:`struct ssh_command `”h]”h)”}”(hŒ*:c:type:`struct ssh_command `”h]”hÓ)”}”(hj h]”hŒstruct ssh_command”…””}”(hj¢h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjžubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒ ssh_command”uh1hh³hÇh´Khjšubah}”(h]”h ]”h"]”Œ ssh_command”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒE.. |ssh_request| replace:: :c:type:`struct ssh_request `”h]”h)”}”(hŒ*:c:type:`struct ssh_request `”h]”hÓ)”}”(hjÊh]”hŒstruct ssh_request”…””}”(hjÌh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjÈubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒ ssh_request”uh1hh³hÇh´KhjÄubah}”(h]”h ]”h"]”Œ ssh_request”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ8.. |ssh_request_get| replace:: :c:func:`ssh_request_get`”h]”h)”}”(hŒ:c:func:`ssh_request_get`”h]”hÓ)”}”(hjôh]”hŒssh_request_get()”…””}”(hjöh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjòubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_request_get”uh1hh³hÇh´Khjîubah}”(h]”h ]”h"]”Œssh_request_get”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ8.. |ssh_request_put| replace:: :c:func:`ssh_request_put`”h]”h)”}”(hŒ:c:func:`ssh_request_put`”h]”hÓ)”}”(hjh]”hŒssh_request_put()”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_request_put”uh1hh³hÇh´Khjubah}”(h]”h ]”h"]”Œssh_request_put”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒQ.. |ssh_request_ops| replace:: :c:type:`struct ssh_request_ops `”h]”h)”}”(hŒ2:c:type:`struct ssh_request_ops `”h]”hÓ)”}”(hjHh]”hŒstruct ssh_request_ops”…””}”(hjJh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjFubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssh_request_ops”uh1hh³hÇh´KhjBubah}”(h]”h ]”h"]”Œssh_request_ops”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ:.. |ssh_request_init| replace:: :c:func:`ssh_request_init`”h]”h)”}”(hŒ:c:func:`ssh_request_init`”h]”hÓ)”}”(hjrh]”hŒssh_request_init()”…””}”(hjth²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjpubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssh_request_init”uh1hh³hÇh´Khjlubah}”(h]”h ]”h"]”Œssh_request_init”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒU.. |ssh_request_flags| replace:: :c:type:`enum ssh_request_flags `”h]”h)”}”(hŒ4:c:type:`enum ssh_request_flags `”h]”hÓ)”}”(hjœh]”hŒenum ssh_request_flags”…””}”(hjžh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjšubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssh_request_flags”uh1hh³hÇh´Khj–ubah}”(h]”h ]”h"]”Œssh_request_flags”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒQ.. |ssam_controller| replace:: :c:type:`struct ssam_controller `”h]”h)”}”(hŒ2:c:type:`struct ssam_controller `”h]”hÓ)”}”(hjÆh]”hŒstruct ssam_controller”…””}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjÄubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssam_controller”uh1hh³hÇh´KhjÀubah}”(h]”h ]”h"]”Œssam_controller”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒE.. |ssam_device| replace:: :c:type:`struct ssam_device `”h]”h)”}”(hŒ*:c:type:`struct ssam_device `”h]”hÓ)”}”(hjðh]”hŒstruct ssam_device”…””}”(hjòh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjîubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒ ssam_device”uh1hh³hÇh´Khjêubah}”(h]”h ]”h"]”Œ ssam_device”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒZ.. |ssam_device_driver| replace:: :c:type:`struct ssam_device_driver `”h]”h)”}”(hŒ8:c:type:`struct ssam_device_driver `”h]”hÓ)”}”(hjh]”hŒstruct ssam_device_driver”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssam_device_driver”uh1hh³hÇh´Khjubah}”(h]”h ]”h"]”Œssam_device_driver”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ:.. |ssam_client_bind| replace:: :c:func:`ssam_client_bind`”h]”h)”}”(hŒ:c:func:`ssam_client_bind`”h]”hÓ)”}”(hjDh]”hŒssam_client_bind()”…””}”(hjFh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjBubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssam_client_bind”uh1hh³hÇh´Khj>ubah}”(h]”h ]”h"]”Œssam_client_bind”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒ:.. |ssam_client_link| replace:: :c:func:`ssam_client_link`”h]”h)”}”(hŒ:c:func:`ssam_client_link`”h]”hÓ)”}”(hjnh]”hŒssam_client_link()”…””}”(hjph²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjlubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssam_client_link”uh1hh³hÇh´Khjhubah}”(h]”h ]”h"]”Œssam_client_link”ah$]”h&]”uh1hÈh³hÇh´Khhh²hubhÉ)”}”(hŒW.. |ssam_request_sync| replace:: :c:type:`struct ssam_request_sync `”h]”h)”}”(hŒ6:c:type:`struct ssam_request_sync `”h]”hÓ)”}”(hj˜h]”hŒstruct ssam_request_sync”…””}”(hjšh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhj–ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssam_request_sync”uh1hh³hÇh´K hj’ubah}”(h]”h ]”h"]”Œssam_request_sync”ah$]”h&]”uh1hÈh³hÇh´K hhh²hubhÉ)”}”(hŒ].. |ssam_event_registry| replace:: :c:type:`struct ssam_event_registry `”h]”h)”}”(hŒ::c:type:`struct ssam_event_registry `”h]”hÓ)”}”(hjÂh]”hŒstruct ssam_event_registry”…””}”(hjÄh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjÀubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssam_event_registry”uh1hh³hÇh´K!hj¼ubah}”(h]”h ]”h"]”Œssam_event_registry”ah$]”h&]”uh1hÈh³hÇh´K!hhh²hubhÉ)”}”(hŒK.. |ssam_event_id| replace:: :c:type:`struct ssam_event_id `”h]”h)”}”(hŒ.:c:type:`struct ssam_event_id `”h]”hÓ)”}”(hjìh]”hŒstruct ssam_event_id”…””}”(hjîh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjêubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒ ssam_event_id”uh1hh³hÇh´K"hjæubah}”(h]”h ]”h"]”Œ ssam_event_id”ah$]”h&]”uh1hÈh³hÇh´K"hhh²hubhÉ)”}”(hŒ9.. |ssam_nf| replace:: :c:type:`struct ssam_nf `”h]”h)”}”(hŒ":c:type:`struct ssam_nf `”h]”hÓ)”}”(hjh]”hŒstruct ssam_nf”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssam_nf”uh1hh³hÇh´K#hjubah}”(h]”h ]”h"]”Œssam_nf”ah$]”h&]”uh1hÈh³hÇh´K#hhh²hubhÉ)”}”(hŒB.. |ssam_nf_refcount_inc| replace:: :c:func:`ssam_nf_refcount_inc`”h]”h)”}”(hŒ:c:func:`ssam_nf_refcount_inc`”h]”hÓ)”}”(hj@h]”hŒssam_nf_refcount_inc()”…””}”(hjBh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhj>ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssam_nf_refcount_inc”uh1hh³hÇh´K$hj:ubah}”(h]”h ]”h"]”Œssam_nf_refcount_inc”ah$]”h&]”uh1hÈh³hÇh´K$hhh²hubhÉ)”}”(hŒB.. |ssam_nf_refcount_dec| replace:: :c:func:`ssam_nf_refcount_dec`”h]”h)”}”(hŒ:c:func:`ssam_nf_refcount_dec`”h]”hÓ)”}”(hjjh]”hŒssam_nf_refcount_dec()”…””}”(hjlh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhjhubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssam_nf_refcount_dec”uh1hh³hÇh´K%hjdubah}”(h]”h ]”h"]”Œssam_nf_refcount_dec”ah$]”h&]”uh1hÈh³hÇh´K%hhh²hubhÉ)”}”(hŒF.. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register`”h]”h)”}”(hŒ :c:func:`ssam_notifier_register`”h]”hÓ)”}”(hj”h]”hŒssam_notifier_register()”…””}”(hj–h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhj’ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssam_notifier_register”uh1hh³hÇh´K&hjŽubah}”(h]”h ]”h"]”Œssam_notifier_register”ah$]”h&]”uh1hÈh³hÇh´K&hhh²hubhÉ)”}”(hŒJ.. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister`”h]”h)”}”(hŒ":c:func:`ssam_notifier_unregister`”h]”hÓ)”}”(hj¾h]”hŒssam_notifier_unregister()”…””}”(hjÀh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhj¼ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssam_notifier_unregister”uh1hh³hÇh´K'hj¸ubah}”(h]”h ]”h"]”Œssam_notifier_unregister”ah$]”h&]”uh1hÈh³hÇh´K'hhh²hubhÉ)”}”(hŒ?.. |ssam_cplt| replace:: :c:type:`struct ssam_cplt `”h]”h)”}”(hŒ&:c:type:`struct ssam_cplt `”h]”hÓ)”}”(hjèh]”hŒstruct ssam_cplt”…””}”(hjêh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjæubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒ ssam_cplt”uh1hh³hÇh´K(hjâubah}”(h]”h ]”h"]”Œ ssam_cplt”ah$]”h&]”uh1hÈh³hÇh´K(hhh²hubhÉ)”}”(hŒT.. |ssam_event_queue| replace:: :c:type:`struct ssam_event_queue `”h]”h)”}”(hŒ4:c:type:`struct ssam_event_queue `”h]”hÓ)”}”(hjh]”hŒstruct ssam_event_queue”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-type”eh"]”h$]”h&]”uh1hÒhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰hñŒssam_event_queue”uh1hh³hÇh´K)hj ubah}”(h]”h ]”h"]”Œssam_event_queue”ah$]”h&]”uh1hÈh³hÇh´K)hhh²hubhÉ)”}”(hŒK.. |ssam_request_sync_submit| replace:: :c:func:`ssam_request_sync_submit` ”h]”h)”}”(hŒ":c:func:`ssam_request_sync_submit`”h]”hÓ)”}”(hj<h]”hŒssam_request_sync_submit()”…””}”(hj>h²hh³Nh´Nubah}”(h]”h ]”(hÞhߌc-func”eh"]”h$]”h&]”uh1hÒhj:ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”Œfunc”Œ refexplicit”‰Œrefwarn”‰hñŒssam_request_sync_submit”uh1hh³hÇh´K*hj6ubah}”(h]”h ]”h"]”Œssam_request_sync_submit”ah$]”h&]”uh1hÈh³hÇh´K*hhh²hubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒCore Driver Internals”h]”hŒCore Driver Internals”…””}”(hjgh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjbh²hh³hÇh´K.ubhŒ paragraph”“”)”}”(hŒ”Architectural overview of the Surface System Aggregator Module (SSAM) core and Surface Serial Hub (SSH) driver. For the API documentation, refer to:”h]”hŒ”Architectural overview of the Surface System Aggregator Module (SSAM) core and Surface Serial Hub (SSH) driver. For the API documentation, refer to:”…””}”(hjwh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K0hjbh²hubhŒcompound”“”)”}”(hhh]”hŒtoctree”“”)”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”hhëŒentries”]”NŒ*driver-api/surface_aggregator/internal-api”†”aŒ includefiles”]”j—aŒmaxdepth”KŒcaption”NŒglob”‰Œhidden”‰Œ includehidden”‰Œnumbered”KŒ titlesonly”‰Œ rawentries”]”uh1jŠh³hÇh´K3hj‡ubah}”(h]”h ]”Œtoctree-wrapper”ah"]”h$]”h&]”uh1j…hjbh²hh³hÇh´Nubja)”}”(hhh]”(jf)”}”(hŒOverview”h]”hŒOverview”…””}”(hj®h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehj«h²hh³hÇh´K:ubjv)”}”(hŒdThe SSAM core implementation is structured in layers, somewhat following the SSH protocol structure:”h]”hŒdThe SSAM core implementation is structured in layers, somewhat following the SSH protocol structure:”…””}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”j’uh1hh³hÇh´Khj h²hubhŒ).”…””}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´Kjhj h²hubjv)”}”(hXAThis structure contains the required fields to manage the packet inside the transport layer, as well as a reference to the buffer containing the data to be transmitted (i.e. the message wrapped in |ssh_frame|). Most notably, it contains an internal reference count, which is used for managing its lifetime (accessible via |ssh_packet_get| and |ssh_packet_put|). When this counter reaches zero, the ``release()`` callback provided to the packet via its |ssh_packet_ops| reference is executed, which may then deallocate the packet or its enclosing structure (e.g. |ssh_request|).”h]”(hŒÅThis structure contains the required fields to manage the packet inside the transport layer, as well as a reference to the buffer containing the data to be transmitted (i.e. the message wrapped in ”…””}”(hjd h²hh³Nh´Nubh)”}”(hjvh]”hÓ)”}”(hjvh]”hŒstruct ssh_frame”…””}”(hjo h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj‚eh"]”h$]”h&]”uh1hÒh³Nh´Nhjl ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”j’uh1hh³hÇh´Khjd h²hubhŒr). Most notably, it contains an internal reference count, which is used for managing its lifetime (accessible via ”…””}”(hjd h²hh³Nh´Nubh)”}”(hjzh]”hÓ)”}”(hjzh]”hŒssh_packet_get()”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj†eh"]”h$]”h&]”uh1hÒh³Nh´NhjŒ ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j“Œ refexplicit”‰Œrefwarn”‰Œ reftarget”j–uh1hh³hÇh´K hjd h²hubhŒ and ”…””}”(hjd h²hh³Nh´Nubh)”}”(hj¤h]”hÓ)”}”(hj¤h]”hŒssh_packet_put()”…””}”(hj¯ h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj°eh"]”h$]”h&]”uh1hÒh³Nh´Nhj¬ ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j½Œ refexplicit”‰Œrefwarn”‰Œ reftarget”jÀuh1hh³hÇh´Khjd h²hubhŒ'). When this counter reaches zero, the ”…””}”(hjd h²hh³Nh´NubhÓ)”}”(hŒ ``release()``”h]”hŒ release()”…””}”(hjÌ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjd ubhŒ) callback provided to the packet via its ”…””}”(hjd h²hh³Nh´Nubh)”}”(hjÎh]”hÓ)”}”(hjÎh]”hŒstruct ssh_packet_ops”…””}”(hjá h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÚeh"]”h$]”h&]”uh1hÒh³Nh´NhjÞ ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jçŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”jêuh1hh³hÇh´Khjd h²hubhŒ^ reference is executed, which may then deallocate the packet or its enclosing structure (e.g. ”…””}”(hjd h²hh³Nh´Nubh)”}”(hjÊh]”hÓ)”}”(hjÊh]”hŒstruct ssh_request”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÖeh"]”h$]”h&]”uh1hÒh³Nh´Nhjþ ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j㌠refexplicit”ˆŒrefwarn”‰Œ reftarget”jæuh1hh³hÇh´Khjd h²hubhŒ).”…””}”(hjd h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´Kqhj h²hubjv)”}”(hX7In addition to the ``release`` callback, the |ssh_packet_ops| reference also provides a ``complete()`` callback, which is run once the packet has been completed and provides the status of this completion, i.e. zero on success or a negative errno value in case of an error. Once the packet has been submitted to the packet transport layer, the ``complete()`` callback is always guaranteed to be executed before the ``release()`` callback, i.e. the packet will always be completed, either successfully, with an error, or due to cancellation, before it will be released.”h]”(hŒIn addition to the ”…””}”(hj$ h²hh³Nh´NubhÓ)”}”(hŒ ``release``”h]”hŒrelease”…””}”(hj, h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj$ ubhŒ callback, the ”…””}”(hj$ h²hh³Nh´Nubh)”}”(hjÎh]”hÓ)”}”(hjÎh]”hŒstruct ssh_packet_ops”…””}”(hjA h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÚeh"]”h$]”h&]”uh1hÒh³Nh´Nhj> ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jçŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”jêuh1hh³hÇh´Khj$ h²hubhŒ reference also provides a ”…””}”(hj$ h²hh³Nh´NubhÓ)”}”(hŒ``complete()``”h]”hŒ complete()”…””}”(hj^ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj$ ubhŒñ callback, which is run once the packet has been completed and provides the status of this completion, i.e. zero on success or a negative errno value in case of an error. Once the packet has been submitted to the packet transport layer, the ”…””}”(hj$ h²hh³Nh´NubhÓ)”}”(hŒ``complete()``”h]”hŒ complete()”…””}”(hjp h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj$ ubhŒ9 callback is always guaranteed to be executed before the ”…””}”(hj$ h²hh³Nh´NubhÓ)”}”(hŒ ``release()``”h]”hŒ release()”…””}”(hj‚ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj$ ubhŒŒ callback, i.e. the packet will always be completed, either successfully, with an error, or due to cancellation, before it will be released.”…””}”(hj$ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´Kzhj h²hubjv)”}”(hŒ¥The state of a packet is managed via its ``state`` flags (|ssh_packet_flags|), which also contains the packet type. In particular, the following bits are noteworthy:”h]”(hŒ)The state of a packet is managed via its ”…””}”(hjš h²hh³Nh´NubhÓ)”}”(hŒ ``state``”h]”hŒstate”…””}”(hj¢ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjš ubhŒ flags (”…””}”(hjš h²hh³Nh´Nubh)”}”(hj"h]”hÓ)”}”(hj"h]”hŒenum ssh_packet_flags”…””}”(hj· h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj.eh"]”h$]”h&]”uh1hÒh³Nh´Nhj´ ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j;Œ refexplicit”ˆŒrefwarn”‰Œ reftarget”j>uh1hh³hÇh´Khjš h²hubhŒY), which also contains the packet type. In particular, the following bits are noteworthy:”…””}”(hjš h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´Kƒhj h²hubhŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hXt``SSH_PACKET_SF_LOCKED_BIT``: This bit is set when completion, either through error or success, is imminent. It indicates that no further references of the packet should be taken and any existing references should be dropped as soon as possible. The process setting this bit is responsible for removing any references to this packet from the packet queue and pending set. ”h]”jv)”}”(hXs``SSH_PACKET_SF_LOCKED_BIT``: This bit is set when completion, either through error or success, is imminent. It indicates that no further references of the packet should be taken and any existing references should be dropped as soon as possible. The process setting this bit is responsible for removing any references to this packet from the packet queue and pending set.”h]”(hÓ)”}”(hŒ``SSH_PACKET_SF_LOCKED_BIT``”h]”hŒSSH_PACKET_SF_LOCKED_BIT”…””}”(hjé h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjå ubhXW: This bit is set when completion, either through error or success, is imminent. It indicates that no further references of the packet should be taken and any existing references should be dropped as soon as possible. The process setting this bit is responsible for removing any references to this packet from the packet queue and pending set.”…””}”(hjå h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K‡hjá ubah}”(h]”h ]”h"]”h$]”h&]”uh1jß hjÜ h²hh³hÇh´Nubjà )”}”(hŒ``SSH_PACKET_SF_COMPLETED_BIT``: This bit is set by the process running the ``complete()`` callback and is used to ensure that this callback only runs once. ”h]”jv)”}”(hŒœ``SSH_PACKET_SF_COMPLETED_BIT``: This bit is set by the process running the ``complete()`` callback and is used to ensure that this callback only runs once.”h]”(hÓ)”}”(hŒ``SSH_PACKET_SF_COMPLETED_BIT``”h]”hŒSSH_PACKET_SF_COMPLETED_BIT”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj ubhŒ-: This bit is set by the process running the ”…””}”(hj h²hh³Nh´NubhÓ)”}”(hŒ``complete()``”h]”hŒ complete()”…””}”(hj! h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj ubhŒB callback and is used to ensure that this callback only runs once.”…””}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KŽhj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jß hjÜ h²hh³hÇh´Nubjà )”}”(hŒ}``SSH_PACKET_SF_QUEUED_BIT``: This bit is set when the packet is queued on the packet queue and cleared when it is dequeued. ”h]”jv)”}”(hŒ|``SSH_PACKET_SF_QUEUED_BIT``: This bit is set when the packet is queued on the packet queue and cleared when it is dequeued.”h]”(hÓ)”}”(hŒ``SSH_PACKET_SF_QUEUED_BIT``”h]”hŒSSH_PACKET_SF_QUEUED_BIT”…””}”(hjG h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjC ubhŒ`: This bit is set when the packet is queued on the packet queue and cleared when it is dequeued.”…””}”(hjC h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K’hj? ubah}”(h]”h ]”h"]”h$]”h&]”uh1jß hjÜ h²hh³hÇh´Nubjà )”}”(hŒƒ``SSH_PACKET_SF_PENDING_BIT``: This bit is set when the packet is added to the pending set and cleared when it is removed from it. ”h]”jv)”}”(hŒ‚``SSH_PACKET_SF_PENDING_BIT``: This bit is set when the packet is added to the pending set and cleared when it is removed from it.”h]”(hÓ)”}”(hŒ``SSH_PACKET_SF_PENDING_BIT``”h]”hŒSSH_PACKET_SF_PENDING_BIT”…””}”(hjm h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhji ubhŒe: This bit is set when the packet is added to the pending set and cleared when it is removed from it.”…””}”(hji h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K•hje ubah}”(h]”h ]”h"]”h$]”h&]”uh1jß hjÜ h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ*”uh1jÚ h³hÇh´K‡hj h²hubeh}”(h]”Œpackets”ah ]”h"]”Œpackets”ah$]”h&]”uh1j`hjÆh²hh³hÇh´Khubja)”}”(hhh]”(jf)”}”(hŒ Packet Queue”h]”hŒ Packet Queue”…””}”(hjž h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehj› h²hh³hÇh´K™ubjv)”}”(hXThe packet queue is the first of the two fundamental collections in the packet transport layer. It is a priority queue, with priority of the respective packets based on the packet type (major) and number of tries (minor). See |SSH_PACKET_PRIORITY| for more details on the priority value.”h]”(hŒâThe packet queue is the first of the two fundamental collections in the packet transport layer. It is a priority queue, with priority of the respective packets based on the packet type (major) and number of tries (minor). See ”…””}”(hj¬ h²hh³Nh´Nubh)”}”(hjLh]”hÓ)”}”(hjLh]”hŒSSH_PACKET_PRIORITY()”…””}”(hj· h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjXeh"]”h$]”h&]”uh1hÒh³Nh´Nhj´ ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jeŒ refexplicit”‰Œrefwarn”‰Œ reftarget”jhuh1hh³hÇh´Khj¬ h²hubhŒ( for more details on the priority value.”…””}”(hj¬ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K›hj› h²hubjv)”}”(hX All packets to be transmitted by the transport layer must be submitted to this queue via |ssh_ptl_submit|. Note that this includes control packets sent by the transport layer itself. Internally, data packets can be re-submitted to this queue due to timeouts or NAK packets sent by the EC.”h]”(hŒYAll packets to be transmitted by the transport layer must be submitted to this queue via ”…””}”(hjÚ h²hh³Nh´Nubh)”}”(hjh]”hÓ)”}”(hjh]”hŒssh_ptl_submit()”…””}”(hjå h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj eh"]”h$]”h&]”uh1hÒh³Nh´Nhjâ ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jŒ refexplicit”‰Œrefwarn”‰Œ reftarget”juh1hh³hÇh´KhjÚ h²hubhŒ·. Note that this includes control packets sent by the transport layer itself. Internally, data packets can be re-submitted to this queue due to timeouts or NAK packets sent by the EC.”…””}”(hjÚ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K hj› h²hubeh}”(h]”Œ packet-queue”ah ]”h"]”Œ packet queue”ah$]”h&]”uh1j`hjÆh²hh³hÇh´K™ubja)”}”(hhh]”(jf)”}”(hŒ Pending Set”h]”hŒ Pending Set”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehj h²hh³hÇh´K¦ubjv)”}”(hŒîThe pending set is the second of the two fundamental collections in the packet transport layer. It stores references to packets that have already been transmitted, but wait for acknowledgment (e.g. the corresponding ACK packet) by the EC.”h]”hŒîThe pending set is the second of the two fundamental collections in the packet transport layer. It stores references to packets that have already been transmitted, but wait for acknowledgment (e.g. the corresponding ACK packet) by the EC.”…””}”(hj! h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K¨hj h²hubjv)”}”(hŒÃNote that a packet may both be pending and queued if it has been re-submitted due to a packet acknowledgment timeout or NAK. On such a re-submission, packets are not removed from the pending set.”h]”hŒÃNote that a packet may both be pending and queued if it has been re-submitted due to a packet acknowledgment timeout or NAK. On such a re-submission, packets are not removed from the pending set.”…””}”(hj/ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K­hj h²hubeh}”(h]”Œ pending-set”ah ]”h"]”h$]”Œ pending set”ah&]”uh1j`hjÆh²hh³hÇh´K¦Œ referenced”Kubja)”}”(hhh]”(jf)”}”(hŒTransmitter Thread”h]”hŒTransmitter Thread”…””}”(hjI h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjF h²hh³hÇh´K²ubjv)”}”(hX The transmitter thread is responsible for most of the actual work regarding packet transmission. In each iteration, it (waits for and) checks if the next packet on the queue (if any) can be transmitted and, if so, removes it from the queue and increments its counter for the number of transmission attempts, i.e. tries. If the packet is sequenced, i.e. requires an ACK by the EC, the packet is added to the pending set. Next, the packet's data is submitted to the serdev subsystem. In case of an error or timeout during this submission, the packet is completed by the transmitter thread with the status value of the callback set accordingly. In case the packet is unsequenced, i.e. does not require an ACK by the EC, the packet is completed with success on the transmitter thread.”h]”hXThe transmitter thread is responsible for most of the actual work regarding packet transmission. In each iteration, it (waits for and) checks if the next packet on the queue (if any) can be transmitted and, if so, removes it from the queue and increments its counter for the number of transmission attempts, i.e. tries. If the packet is sequenced, i.e. requires an ACK by the EC, the packet is added to the pending set. Next, the packet’s data is submitted to the serdev subsystem. In case of an error or timeout during this submission, the packet is completed by the transmitter thread with the status value of the callback set accordingly. In case the packet is unsequenced, i.e. does not require an ACK by the EC, the packet is completed with success on the transmitter thread.”…””}”(hjW h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´K´hjF h²hubjv)”}”(hXiTransmission of sequenced packets is limited by the number of concurrently pending packets, i.e. a limit on how many packets may be waiting for an ACK from the EC in parallel. This limit is currently set to one (see Documentation/driver-api/surface_aggregator/ssh.rst for the reasoning behind this). Control packets (i.e. ACK and NAK) can always be transmitted.”h]”hXiTransmission of sequenced packets is limited by the number of concurrently pending packets, i.e. a limit on how many packets may be waiting for an ACK from the EC in parallel. This limit is currently set to one (see Documentation/driver-api/surface_aggregator/ssh.rst for the reasoning behind this). Control packets (i.e. ACK and NAK) can always be transmitted.”…””}”(hje h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KÀhjF h²hubeh}”(h]”Œtransmitter-thread”ah ]”h"]”Œtransmitter thread”ah$]”h&]”uh1j`hjÆh²hh³hÇh´K²ubja)”}”(hhh]”(jf)”}”(hŒReceiver Thread”h]”hŒReceiver Thread”…””}”(hj~ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehj{ h²hh³hÇh´KÇubjv)”}”(hXhAny data received from the EC is put into a FIFO buffer for further processing. This processing happens on the receiver thread. The receiver thread parses and validates the received message into its |ssh_frame| and corresponding payload. It prepares and submits the necessary ACK (and on validation error or invalid data NAK) packets for the received messages.”h]”(hŒÇAny data received from the EC is put into a FIFO buffer for further processing. This processing happens on the receiver thread. The receiver thread parses and validates the received message into its ”…””}”(hjŒ h²hh³Nh´Nubh)”}”(hjvh]”hÓ)”}”(hjvh]”hŒstruct ssh_frame”…””}”(hj— h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj‚eh"]”h$]”h&]”uh1hÒh³Nh´Nhj” ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”j’uh1hh³hÇh´KhjŒ h²hubhŒ– and corresponding payload. It prepares and submits the necessary ACK (and on validation error or invalid data NAK) packets for the received messages.”…””}”(hjŒ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KÉhj{ h²hubjv)”}”(hX'This thread also handles further processing, such as matching ACK messages to the corresponding pending packet (via sequence ID) and completing it, as well as initiating re-submission of all currently pending packets on receival of a NAK message (re-submission in case of a NAK is similar to re-submission due to timeout, see below for more details on that). Note that the successful completion of a sequenced packet will always run on the receiver thread (whereas any failure-indicating completion will run on the process where the failure occurred).”h]”hX'This thread also handles further processing, such as matching ACK messages to the corresponding pending packet (via sequence ID) and completing it, as well as initiating re-submission of all currently pending packets on receival of a NAK message (re-submission in case of a NAK is similar to re-submission due to timeout, see below for more details on that). Note that the successful completion of a sequenced packet will always run on the receiver thread (whereas any failure-indicating completion will run on the process where the failure occurred).”…””}”(hjº h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KÏhj{ h²hubjv)”}”(hŒgAny payload data is forwarded via a callback to the next upper layer, i.e. the request transport layer.”h]”hŒgAny payload data is forwarded via a callback to the next upper layer, i.e. the request transport layer.”…””}”(hjÈ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KØhj{ h²hubeh}”(h]”Œreceiver-thread”ah ]”h"]”Œreceiver thread”ah$]”h&]”uh1j`hjÆh²hh³hÇh´KÇubja)”}”(hhh]”(jf)”}”(hŒTimeout Reaper”h]”hŒTimeout Reaper”…””}”(hjá h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjÞ h²hh³hÇh´KÜubjv)”}”(hX^The packet acknowledgment timeout is a per-packet timeout for sequenced packets, started when the respective packet begins (re-)transmission (i.e. this timeout is armed once per transmission attempt on the transmitter thread). It is used to trigger re-submission or, when the number of tries has been exceeded, cancellation of the packet in question.”h]”hX^The packet acknowledgment timeout is a per-packet timeout for sequenced packets, started when the respective packet begins (re-)transmission (i.e. this timeout is armed once per transmission attempt on the transmitter thread). It is used to trigger re-submission or, when the number of tries has been exceeded, cancellation of the packet in question.”…””}”(hjï h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KÞhjÞ h²hubjv)”}”(hX\This timeout is handled via a dedicated reaper task, which is essentially a work item (re-)scheduled to run when the next packet is set to time out. The work item then checks the set of pending packets for any packets that have exceeded the timeout and, if there are any remaining packets, re-schedules itself to the next appropriate point in time.”h]”hX\This timeout is handled via a dedicated reaper task, which is essentially a work item (re-)scheduled to run when the next packet is set to time out. The work item then checks the set of pending packets for any packets that have exceeded the timeout and, if there are any remaining packets, re-schedules itself to the next appropriate point in time.”…””}”(hjý h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KähjÞ h²hubjv)”}”(hXçIf a timeout has been detected by the reaper, the packet will either be re-submitted if it still has some remaining tries left, or completed with ``-ETIMEDOUT`` as status if not. Note that re-submission, in this case and triggered by receival of a NAK, means that the packet is added to the queue with a now incremented number of tries, yielding a higher priority. The timeout for the packet will be disabled until the next transmission attempt and the packet remains on the pending set.”h]”(hŒ’If a timeout has been detected by the reaper, the packet will either be re-submitted if it still has some remaining tries left, or completed with ”…””}”(hj h²hh³Nh´NubhÓ)”}”(hŒ``-ETIMEDOUT``”h]”hŒ -ETIMEDOUT”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj ubhXG as status if not. Note that re-submission, in this case and triggered by receival of a NAK, means that the packet is added to the queue with a now incremented number of tries, yielding a higher priority. The timeout for the packet will be disabled until the next transmission attempt and the packet remains on the pending set.”…””}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KêhjÞ h²hubjv)”}”(hŒÃNote that due to transmission and packet acknowledgment timeouts, the packet transport layer is always guaranteed to make progress, if only through timing out packets, and will never fully block.”h]”hŒÃNote that due to transmission and packet acknowledgment timeouts, the packet transport layer is always guaranteed to make progress, if only through timing out packets, and will never fully block.”…””}”(hj+ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KòhjÞ h²hubeh}”(h]”Œtimeout-reaper”ah ]”h"]”h$]”Œtimeout reaper”ah&]”uh1j`hjÆh²hh³hÇh´KÜjE Kubja)”}”(hhh]”(jf)”}”(hŒConcurrency and Locking”h]”hŒConcurrency and Locking”…””}”(hjD h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjA h²hh³hÇh´K÷ubjv)”}”(hXOThere are two main locks in the packet transport layer: One guarding access to the packet queue and one guarding access to the pending set. These collections may only be accessed and modified under the respective lock. If access to both collections is needed, the pending lock must be acquired before the queue lock to avoid deadlocks.”h]”hXOThere are two main locks in the packet transport layer: One guarding access to the packet queue and one guarding access to the pending set. These collections may only be accessed and modified under the respective lock. If access to both collections is needed, the pending lock must be acquired before the queue lock to avoid deadlocks.”…””}”(hjR h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KùhjA h²hubjv)”}”(hX/In addition to guarding the collections, after initial packet submission certain packet fields may only be accessed under one of the locks. Specifically, the packet priority must only be accessed while holding the queue lock and the packet timestamp must only be accessed while holding the pending lock.”h]”hX/In addition to guarding the collections, after initial packet submission certain packet fields may only be accessed under one of the locks. Specifically, the packet priority must only be accessed while holding the queue lock and the packet timestamp must only be accessed while holding the pending lock.”…””}”(hj` h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´KÿhjA h²hubjv)”}”(hŒúOther parts of the packet transport layer are guarded independently. State flags are managed by atomic bit operations and, if necessary, memory barriers. Modifications to the timeout reaper work item and expiration date are guarded by their own lock.”h]”hŒúOther parts of the packet transport layer are guarded independently. State flags are managed by atomic bit operations and, if necessary, memory barriers. Modifications to the timeout reaper work item and expiration date are guarded by their own lock.”…””}”(hjn h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MhjA h²hubjv)”}”(hXThe reference of the packet to the packet transport layer (``ptl``) is somewhat special. It is either set when the upper layer request is submitted or, if there is none, when the packet is first submitted. After it is set, it will not change its value. Functions that may run concurrently with submission, i.e. cancellation, can not rely on the ``ptl`` reference to be set. Access to it in these functions is guarded by ``READ_ONCE()``, whereas setting ``ptl`` is equally guarded with ``WRITE_ONCE()`` for symmetry.”h]”(hŒ;The reference of the packet to the packet transport layer (”…””}”(hj| h²hh³Nh´NubhÓ)”}”(hŒ``ptl``”h]”hŒptl”…””}”(hj„ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj| ubhX) is somewhat special. It is either set when the upper layer request is submitted or, if there is none, when the packet is first submitted. After it is set, it will not change its value. Functions that may run concurrently with submission, i.e. cancellation, can not rely on the ”…””}”(hj| h²hh³Nh´NubhÓ)”}”(hŒ``ptl``”h]”hŒptl”…””}”(hj– h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj| ubhŒD reference to be set. Access to it in these functions is guarded by ”…””}”(hj| h²hh³Nh´NubhÓ)”}”(hŒ``READ_ONCE()``”h]”hŒ READ_ONCE()”…””}”(hj¨ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj| ubhŒ, whereas setting ”…””}”(hj| h²hh³Nh´NubhÓ)”}”(hŒ``ptl``”h]”hŒptl”…””}”(hjº h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj| ubhŒ is equally guarded with ”…””}”(hj| h²hh³Nh´NubhÓ)”}”(hŒ``WRITE_ONCE()``”h]”hŒ WRITE_ONCE()”…””}”(hjÌ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj| ubhŒ for symmetry.”…””}”(hj| h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M hjA h²hubjv)”}”(hX Some packet fields may be read outside of the respective locks guarding them, specifically priority and state for tracing. In those cases, proper access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such read-only access is only allowed when stale values are not critical.”h]”(hŒ±Some packet fields may be read outside of the respective locks guarding them, specifically priority and state for tracing. In those cases, proper access is ensured by employing ”…””}”(hjä h²hh³Nh´NubhÓ)”}”(hŒ``WRITE_ONCE()``”h]”hŒ WRITE_ONCE()”…””}”(hjì h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjä ubhŒ and ”…””}”(hjä h²hh³Nh´NubhÓ)”}”(hŒ``READ_ONCE()``”h]”hŒ READ_ONCE()”…””}”(hjþ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjä ubhŒK. Such read-only access is only allowed when stale values are not critical.”…””}”(hjä h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MhjA h²hubjv)”}”(hXßWith respect to the interface for higher layers, packet submission (|ssh_ptl_submit|), packet cancellation (|ssh_ptl_cancel|), data receival (|ssh_ptl_rx_rcvbuf|), and layer shutdown (|ssh_ptl_shutdown|) may always be executed concurrently with respect to each other. Note that packet submission may not run concurrently with itself for the same packet. Equally, shutdown and data receival may also not run concurrently with themselves (but may run concurrently with each other).”h]”(hŒDWith respect to the interface for higher layers, packet submission (”…””}”(hjh²hh³Nh´Nubh)”}”(hjh]”hÓ)”}”(hjh]”hŒssh_ptl_submit()”…””}”(hj!h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj eh"]”h$]”h&]”uh1hÒh³Nh´Nhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jŒ refexplicit”‰Œrefwarn”‰Œ reftarget”juh1hh³hÇh´Khjh²hubhŒ), packet cancellation (”…””}”(hjh²hh³Nh´Nubh)”}”(hj*h]”hÓ)”}”(hj*h]”hŒssh_ptl_cancel()”…””}”(hjAh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj6eh"]”h$]”h&]”uh1hÒh³Nh´Nhj>ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jCŒ refexplicit”‰Œrefwarn”‰Œ reftarget”jFuh1hh³hÇh´Khjh²hubhŒ), data receival (”…””}”(hjh²hh³Nh´Nubh)”}”(hj~h]”hÓ)”}”(hj~h]”hŒssh_ptl_rx_rcvbuf()”…””}”(hjah²hh³Nh´Nubah}”(h]”h ]”(hÞhßjŠeh"]”h$]”h&]”uh1hÒh³Nh´Nhj^ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j—Œ refexplicit”‰Œrefwarn”‰Œ reftarget”jšuh1hh³hÇh´Khjh²hubhŒ), and layer shutdown (”…””}”(hjh²hh³Nh´Nubh)”}”(hjTh]”hÓ)”}”(hjTh]”hŒssh_ptl_shutdown()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj`eh"]”h$]”h&]”uh1hÒh³Nh´Nhj~ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jmŒ refexplicit”‰Œrefwarn”‰Œ reftarget”jpuh1hh³hÇh´Khjh²hubhX) may always be executed concurrently with respect to each other. Note that packet submission may not run concurrently with itself for the same packet. Equally, shutdown and data receival may also not run concurrently with themselves (but may run concurrently with each other).”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MhjA h²hubeh}”(h]”Œconcurrency-and-locking”ah ]”h"]”h$]”Œconcurrency and locking”ah&]”uh1j`hjÆh²hh³hÇh´K÷jE Kubeh}”(h]”Œpacket-transport-layer”ah ]”h"]”Œpacket transport layer”ah$]”h&]”uh1j`hjbh²hh³hÇh´Kbubja)”}”(hhh]”(jf)”}”(hŒRequest Transport Layer”h]”hŒRequest Transport Layer”…””}”(hj·h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehj´h²hh³hÇh´M!ubjv)”}”(hX"The request transport layer is represented via |ssh_rtl| and builds on top of the packet transport layer. It deals with requests, i.e. SSH packets sent by the host containing a |ssh_command| as frame payload. This layer separates responses to requests from events, which are also sent by the EC via a |ssh_command| payload. While responses are handled in this layer, events are relayed to the next upper layer, i.e. the controller layer, via the corresponding callback. The request transport layer is structured around the following key concepts:”h]”(hŒ/The request transport layer is represented via ”…””}”(hjÅh²hh³Nh´Nubh)”}”(hj¨h]”hÓ)”}”(hj¨h]”hŒstruct ssh_rtl”…””}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj´eh"]”h$]”h&]”uh1hÒh³Nh´NhjÍubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jÁŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”jÄuh1hh³hÇh´KhjÅh²hubhŒy and builds on top of the packet transport layer. It deals with requests, i.e. SSH packets sent by the host containing a ”…””}”(hjÅh²hh³Nh´Nubh)”}”(hj h]”hÓ)”}”(hj h]”hŒstruct ssh_command”…””}”(hjðh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj¬eh"]”h$]”h&]”uh1hÒh³Nh´Nhjíubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j¹Œ refexplicit”ˆŒrefwarn”‰Œ reftarget”j¼uh1hh³hÇh´KhjÅh²hubhŒo as frame payload. This layer separates responses to requests from events, which are also sent by the EC via a ”…””}”(hjÅh²hh³Nh´Nubh)”}”(hj h]”hÓ)”}”(hj h]”hŒstruct ssh_command”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj¬eh"]”h$]”h&]”uh1hÒh³Nh´Nhj ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j¹Œ refexplicit”ˆŒrefwarn”‰Œ reftarget”j¼uh1hh³hÇh´KhjÅh²hubhŒè payload. While responses are handled in this layer, events are relayed to the next upper layer, i.e. the controller layer, via the corresponding callback. The request transport layer is structured around the following key concepts:”…””}”(hjÅh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M#hj´h²hubja)”}”(hhh]”(jf)”}”(hŒRequest”h]”hŒRequest”…””}”(hj6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehj3h²hh³hÇh´M-ubjv)”}”(hXxRequests are packets with a command-type payload, sent from host to EC to query data from or trigger an action on it (or both simultaneously). They are represented by |ssh_request|, wrapping the underlying |ssh_packet| storing its message data (i.e. SSH frame with command payload). Note that all top-level representations, e.g. |ssam_request_sync| are built upon this struct.”h]”(hŒ§Requests are packets with a command-type payload, sent from host to EC to query data from or trigger an action on it (or both simultaneously). They are represented by ”…””}”(hjDh²hh³Nh´Nubh)”}”(hjÊh]”hÓ)”}”(hjÊh]”hŒstruct ssh_request”…””}”(hjOh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÖeh"]”h$]”h&]”uh1hÒh³Nh´NhjLubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j㌠refexplicit”ˆŒrefwarn”‰Œ reftarget”jæuh1hh³hÇh´KhjDh²hubhŒ, wrapping the underlying ”…””}”(hjDh²hh³Nh´Nubh)”}”(hjPh]”hÓ)”}”(hjPh]”hŒstruct ssh_packet”…””}”(hjoh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj\eh"]”h$]”h&]”uh1hÒh³Nh´Nhjlubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jiŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”jluh1hh³hÇh´K hjDh²hubhŒo storing its message data (i.e. SSH frame with command payload). Note that all top-level representations, e.g. ”…””}”(hjDh²hh³Nh´Nubh)”}”(hj˜h]”hÓ)”}”(hj˜h]”hŒstruct ssam_request_sync”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj¤eh"]”h$]”h&]”uh1hÒh³Nh´NhjŒubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j±Œ refexplicit”ˆŒrefwarn”‰Œ reftarget”j´uh1hh³hÇh´K hjDh²hubhŒ are built upon this struct.”…””}”(hjDh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M/hj3h²hubjv)”}”(hX1As |ssh_request| extends |ssh_packet|, its lifetime is also managed by the reference counter inside the packet struct (which can be accessed via |ssh_request_get| and |ssh_request_put|). Once the counter reaches zero, the ``release()`` callback of the |ssh_request_ops| reference of the request is called.”h]”(hŒAs ”…””}”(hj²h²hh³Nh´Nubh)”}”(hjÊh]”hÓ)”}”(hjÊh]”hŒstruct ssh_request”…””}”(hj½h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÖeh"]”h$]”h&]”uh1hÒh³Nh´Nhjºubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j㌠refexplicit”ˆŒrefwarn”‰Œ reftarget”jæuh1hh³hÇh´Khj²h²hubhŒ extends ”…””}”(hj²h²hh³Nh´Nubh)”}”(hjPh]”hÓ)”}”(hjPh]”hŒstruct ssh_packet”…””}”(hjÝh²hh³Nh´Nubah}”(h]”h ]”(hÞ•ºÉhßj\eh"]”h$]”h&]”uh1hÒh³Nh´NhjÚubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jiŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”jluh1hh³hÇh´K hj²h²hubhŒl, its lifetime is also managed by the reference counter inside the packet struct (which can be accessed via ”…””}”(hj²h²hh³Nh´Nubh)”}”(hjôh]”hÓ)”}”(hjôh]”hŒssh_request_get()”…””}”(hjýh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjeh"]”h$]”h&]”uh1hÒh³Nh´Nhjúubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j Œ refexplicit”‰Œrefwarn”‰Œ reftarget”juh1hh³hÇh´Khj²h²hubhŒ and ”…””}”(hj²h²hh³Nh´Nubh)”}”(hjh]”hÓ)”}”(hjh]”hŒssh_request_put()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj*eh"]”h$]”h&]”uh1hÒh³Nh´Nhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j7Œ refexplicit”‰Œrefwarn”‰Œ reftarget”j:uh1hh³hÇh´Khj²h²hubhŒ&). Once the counter reaches zero, the ”…””}”(hj²h²hh³Nh´NubhÓ)”}”(hŒ ``release()``”h]”hŒ release()”…””}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj²ubhŒ callback of the ”…””}”(hj²h²hh³Nh´Nubh)”}”(hjHh]”hÓ)”}”(hjHh]”hŒstruct ssh_request_ops”…””}”(hjOh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjTeh"]”h$]”h&]”uh1hÒh³Nh´NhjLubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jaŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”jduh1hh³hÇh´Khj²h²hubhŒ$ reference of the request is called.”…””}”(hj²h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M6hj3h²hubjv)”}”(hXDRequests can have an optional response that is equally sent via a SSH message with command-type payload (from EC to host). The party constructing the request must know if a response is expected and mark this in the request flags provided to |ssh_request_init|, so that the request transport layer can wait for this response.”h]”(hŒñRequests can have an optional response that is equally sent via a SSH message with command-type payload (from EC to host). The party constructing the request must know if a response is expected and mark this in the request flags provided to ”…””}”(hjrh²hh³Nh´Nubh)”}”(hjrh]”hÓ)”}”(hjrh]”hŒssh_request_init()”…””}”(hj}h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj~eh"]”h$]”h&]”uh1hÒh³Nh´Nhjzubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j‹Œ refexplicit”‰Œrefwarn”‰Œ reftarget”jŽuh1hh³hÇh´Khjrh²hubhŒA, so that the request transport layer can wait for this response.”…””}”(hjrh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M<hj3h²hubjv)”}”(hX+Similar to |ssh_packet|, |ssh_request| also has a ``complete()`` callback provided via its request ops reference and is guaranteed to be completed before it is released once it has been submitted to the request transport layer via |ssh_rtl_submit|. For a request without a response, successful completion will occur once the underlying packet has been successfully transmitted by the packet transport layer (i.e. from within the packet completion callback). For a request with response, successful completion will occur once the response has been received and matched to the request via its request ID (which happens on the packet layer's data-received callback running on the receiver thread). If the request is completed with an error, the status value will be set to the corresponding (negative) errno value.”h]”(hŒ Similar to ”…””}”(hj h²hh³Nh´Nubh)”}”(hjPh]”hÓ)”}”(hjPh]”hŒstruct ssh_packet”…””}”(hj«h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj\eh"]”h$]”h&]”uh1hÒh³Nh´Nhj¨ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jiŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”jluh1hh³hÇh´K hj h²hubhŒ, ”…””}”(hj h²hh³Nh´Nubh)”}”(hjÊh]”hÓ)”}”(hjÊh]”hŒstruct ssh_request”…””}”(hjËh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÖeh"]”h$]”h&]”uh1hÒh³Nh´NhjÈubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j㌠refexplicit”ˆŒrefwarn”‰Œ reftarget”jæuh1hh³hÇh´Khj h²hubhŒ also has a ”…””}”(hj h²hh³Nh´NubhÓ)”}”(hŒ``complete()``”h]”hŒ complete()”…””}”(hjèh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj ubhŒ§ callback provided via its request ops reference and is guaranteed to be completed before it is released once it has been submitted to the request transport layer via ”…””}”(hj h²hh³Nh´Nubh)”}”(hjÒh]”hÓ)”}”(hjÒh]”hŒssh_rtl_submit()”…””}”(hjýh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÞeh"]”h$]”h&]”uh1hÒh³Nh´Nhjúubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jëŒ refexplicit”‰Œrefwarn”‰Œ reftarget”jîuh1hh³hÇh´K hj h²hubhX6. For a request without a response, successful completion will occur once the underlying packet has been successfully transmitted by the packet transport layer (i.e. from within the packet completion callback). For a request with response, successful completion will occur once the response has been received and matched to the request via its request ID (which happens on the packet layer’s data-received callback running on the receiver thread). If the request is completed with an error, the status value will be set to the corresponding (negative) errno value.”…””}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MBhj3h²hubjv)”}”(hŒ¬The state of a request is again managed via its ``state`` flags (|ssh_request_flags|), which also encode the request type. In particular, the following bits are noteworthy:”h]”(hŒ0The state of a request is again managed via its ”…””}”(hj h²hh³Nh´NubhÓ)”}”(hŒ ``state``”h]”hŒstate”…””}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj ubhŒ flags (”…””}”(hj h²hh³Nh´Nubh)”}”(hjœh]”hÓ)”}”(hjœh]”hŒenum ssh_request_flags”…””}”(hj=h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj¨eh"]”h$]”h&]”uh1hÒh³Nh´Nhj:ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jµŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”j¸uh1hh³hÇh´Khj h²hubhŒX), which also encode the request type. In particular, the following bits are noteworthy:”…””}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MOhj3h²hubjÛ )”}”(hhh]”(jà )”}”(hXx``SSH_REQUEST_SF_LOCKED_BIT``: This bit is set when completion, either through error or success, is imminent. It indicates that no further references of the request should be taken and any existing references should be dropped as soon as possible. The process setting this bit is responsible for removing any references to this request from the request queue and pending set. ”h]”jv)”}”(hXw``SSH_REQUEST_SF_LOCKED_BIT``: This bit is set when completion, either through error or success, is imminent. It indicates that no further references of the request should be taken and any existing references should be dropped as soon as possible. The process setting this bit is responsible for removing any references to this request from the request queue and pending set.”h]”(hÓ)”}”(hŒ``SSH_REQUEST_SF_LOCKED_BIT``”h]”hŒSSH_REQUEST_SF_LOCKED_BIT”…””}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjgubhXZ: This bit is set when completion, either through error or success, is imminent. It indicates that no further references of the request should be taken and any existing references should be dropped as soon as possible. The process setting this bit is responsible for removing any references to this request from the request queue and pending set.”…””}”(hjgh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MShjcubah}”(h]”h ]”h"]”h$]”h&]”uh1jß hj`h²hh³hÇh´Nubjà )”}”(hŒž``SSH_REQUEST_SF_COMPLETED_BIT``: This bit is set by the process running the ``complete()`` callback and is used to ensure that this callback only runs once. ”h]”jv)”}”(hŒ``SSH_REQUEST_SF_COMPLETED_BIT``: This bit is set by the process running the ``complete()`` callback and is used to ensure that this callback only runs once.”h]”(hÓ)”}”(hŒ ``SSH_REQUEST_SF_COMPLETED_BIT``”h]”hŒSSH_REQUEST_SF_COMPLETED_BIT”…””}”(hj‘h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjubhŒ-: This bit is set by the process running the ”…””}”(hjh²hh³Nh´NubhÓ)”}”(hŒ``complete()``”h]”hŒ complete()”…””}”(hj£h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjubhŒB callback and is used to ensure that this callback only runs once.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MZhj‰ubah}”(h]”h ]”h"]”h$]”h&]”uh1jß hj`h²hh³hÇh´Nubjà )”}”(hŒ€``SSH_REQUEST_SF_QUEUED_BIT``: This bit is set when the request is queued on the request queue and cleared when it is dequeued. ”h]”jv)”}”(hŒ``SSH_REQUEST_SF_QUEUED_BIT``: This bit is set when the request is queued on the request queue and cleared when it is dequeued.”h]”(hÓ)”}”(hŒ``SSH_REQUEST_SF_QUEUED_BIT``”h]”hŒSSH_REQUEST_SF_QUEUED_BIT”…””}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjÅubhŒb: This bit is set when the request is queued on the request queue and cleared when it is dequeued.”…””}”(hjÅh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M^hjÁubah}”(h]”h ]”h"]”h$]”h&]”uh1jß hj`h²hh³hÇh´Nubjà )”}”(hŒ…``SSH_REQUEST_SF_PENDING_BIT``: This bit is set when the request is added to the pending set and cleared when it is removed from it. ”h]”jv)”}”(hŒ„``SSH_REQUEST_SF_PENDING_BIT``: This bit is set when the request is added to the pending set and cleared when it is removed from it.”h]”(hÓ)”}”(hŒ``SSH_REQUEST_SF_PENDING_BIT``”h]”hŒSSH_REQUEST_SF_PENDING_BIT”…””}”(hjïh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjëubhŒf: This bit is set when the request is added to the pending set and cleared when it is removed from it.”…””}”(hjëh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´Mahjçubah}”(h]”h ]”h"]”h$]”h&]”uh1jß hj`h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j‘ j’ uh1jÚ h³hÇh´MShj3h²hubeh}”(h]”Œrequest”ah ]”h"]”Œrequest”ah$]”h&]”uh1j`hj´h²hh³hÇh´M-ubja)”}”(hhh]”(jf)”}”(hŒ Request Queue”h]”hŒ Request Queue”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjh²hh³hÇh´Meubjv)”}”(hŒôThe request queue is the first of the two fundamental collections in the request transport layer. In contrast to the packet queue of the packet transport layer, it is not a priority queue and the simple first come first serve principle applies.”h]”hŒôThe request queue is the first of the two fundamental collections in the request transport layer. In contrast to the packet queue of the packet transport layer, it is not a priority queue and the simple first come first serve principle applies.”…””}”(hj,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´Mghjh²hubjv)”}”(hXAll requests to be transmitted by the request transport layer must be submitted to this queue via |ssh_rtl_submit|. Once submitted, requests may not be re-submitted, and will not be re-submitted automatically on timeout. Instead, the request is completed with a timeout error. If desired, the caller can create and submit a new request for another try, but it must not submit the same request again.”h]”(hŒbAll requests to be transmitted by the request transport layer must be submitted to this queue via ”…””}”(hj:h²hh³Nh´Nubh)”}”(hjÒh]”hÓ)”}”(hjÒh]”hŒssh_rtl_submit()”…””}”(hjEh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÞeh"]”h$]”h&]”uh1hÒh³Nh´NhjBubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jëŒ refexplicit”‰Œrefwarn”‰Œ reftarget”jîuh1hh³hÇh´K hj:h²hubhX. Once submitted, requests may not be re-submitted, and will not be re-submitted automatically on timeout. Instead, the request is completed with a timeout error. If desired, the caller can create and submit a new request for another try, but it must not submit the same request again.”…””}”(hj:h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´Mlhjh²hubeh}”(h]”Œ request-queue”ah ]”h"]”Œ request queue”ah$]”h&]”uh1j`hj´h²hh³hÇh´Meubja)”}”(hhh]”(jf)”}”(hŒ Pending Set”h]”hŒ Pending Set”…””}”(hjsh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjph²hh³hÇh´Mtubjv)”}”(hXThe pending set is the second of the two fundamental collections in the request transport layer. This collection stores references to all pending requests, i.e. requests awaiting a response from the EC (similar to what the pending set of the packet transport layer does for packets).”h]”hXThe pending set is the second of the two fundamental collections in the request transport layer. This collection stores references to all pending requests, i.e. requests awaiting a response from the EC (similar to what the pending set of the packet transport layer does for packets).”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´Mvhjph²hubeh}”(h]”Œid1”ah ]”h"]”h$]”jC ah&]”uh1j`hj´h²hh³hÇh´MtjE Kubja)”}”(hhh]”(jf)”}”(hŒTransmitter Task”h]”hŒTransmitter Task”…””}”(hj™h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehj–h²hh³hÇh´M|ubjv)”}”(hXÇThe transmitter task is scheduled when a new request is available for transmission. It checks if the next request on the request queue can be transmitted and, if so, submits its underlying packet to the packet transport layer. This check ensures that only a limited number of requests can be pending, i.e. waiting for a response, at the same time. If the request requires a response, the request is added to the pending set before its packet is submitted.”h]”hXÇThe transmitter task is scheduled when a new request is available for transmission. It checks if the next request on the request queue can be transmitted and, if so, submits its underlying packet to the packet transport layer. This check ensures that only a limited number of requests can be pending, i.e. waiting for a response, at the same time. If the request requires a response, the request is added to the pending set before its packet is submitted.”…””}”(hj§h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M~hj–h²hubeh}”(h]”Œtransmitter-task”ah ]”h"]”Œtransmitter task”ah$]”h&]”uh1j`hj´h²hh³hÇh´M|ubja)”}”(hhh]”(jf)”}”(hŒPacket Completion Callback”h]”hŒPacket Completion Callback”…””}”(hjÀh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehj½h²hh³hÇh´M‡ubjv)”}”(hŒÝThe packet completion callback is executed once the underlying packet of a request has been completed. In case of an error completion, the corresponding request is completed with the error value provided in this callback.”h]”hŒÝThe packet completion callback is executed once the underlying packet of a request has been completed. In case of an error completion, the corresponding request is completed with the error value provided in this callback.”…””}”(hjÎh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M‰hj½h²hubjv)”}”(hŒ÷On successful packet completion, further processing depends on the request. If the request expects a response, it is marked as transmitted and the request timeout is started. If the request does not expect a response, it is completed with success.”h]”hŒ÷On successful packet completion, further processing depends on the request. If the request expects a response, it is marked as transmitted and the request timeout is started. If the request does not expect a response, it is completed with success.”…””}”(hjÜh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MŽhj½h²hubeh}”(h]”Œpacket-completion-callback”ah ]”h"]”Œpacket completion callback”ah$]”h&]”uh1j`hj´h²hh³hÇh´M‡ubja)”}”(hhh]”(jf)”}”(hŒData-Received Callback”h]”hŒData-Received Callback”…””}”(hjõh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjòh²hh³hÇh´M”ubjv)”}”(hŒÑThe data received callback notifies the request transport layer of data being received by the underlying packet transport layer via a data-type frame. In general, this is expected to be a command-type payload.”h]”hŒÑThe data received callback notifies the request transport layer of data being received by the underlying packet transport layer via a data-type frame. In general, this is expected to be a command-type payload.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M–hjòh²hubjv)”}”(hXvIf the request ID of the command is one of the request IDs reserved for events (one to ``SSH_NUM_EVENTS``, inclusively), it is forwarded to the event callback registered in the request transport layer. If the request ID indicates a response to a request, the respective request is looked up in the pending set and, if found and marked as transmitted, completed with success.”h]”(hŒWIf the request ID of the command is one of the request IDs reserved for events (one to ”…””}”(hjh²hh³Nh´NubhÓ)”}”(hŒ``SSH_NUM_EVENTS``”h]”hŒSSH_NUM_EVENTS”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjubhX , inclusively), it is forwarded to the event callback registered in the request transport layer. If the request ID indicates a response to a request, the respective request is looked up in the pending set and, if found and marked as transmitted, completed with success.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´Mšhjòh²hubeh}”(h]”Œdata-received-callback”ah ]”h"]”Œdata-received callback”ah$]”h&]”uh1j`hj´h²hh³hÇh´M”ubja)”}”(hhh]”(jf)”}”(hŒTimeout Reaper”h]”hŒTimeout Reaper”…””}”(hj<h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehj9h²hh³hÇh´M¢ubjv)”}”(hŒýThe request-response-timeout is a per-request timeout for requests expecting a response. It is used to ensure that a request does not wait indefinitely on a response from the EC and is started after the underlying packet has been successfully completed.”h]”hŒýThe request-response-timeout is a per-request timeout for requests expecting a response. It is used to ensure that a request does not wait indefinitely on a response from the EC and is started after the underlying packet has been successfully completed.”…””}”(hjJh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M¤hj9h²hubjv)”}”(hXþThis timeout is, similar to the packet acknowledgment timeout on the packet transport layer, handled via a dedicated reaper task. This task is essentially a work-item (re-)scheduled to run when the next request is set to time out. The work item then scans the set of pending requests for any requests that have timed out and completes them with ``-ETIMEDOUT`` as status. Requests will not be re-submitted automatically. Instead, the issuer of the request must construct and submit a new request, if so desired.”h]”(hXYThis timeout is, similar to the packet acknowledgment timeout on the packet transport layer, handled via a dedicated reaper task. This task is essentially a work-item (re-)scheduled to run when the next request is set to time out. The work item then scans the set of pending requests for any requests that have timed out and completes them with ”…””}”(hjXh²hh³Nh´NubhÓ)”}”(hŒ``-ETIMEDOUT``”h]”hŒ -ETIMEDOUT”…””}”(hj`h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjXubhŒ— as status. Requests will not be re-submitted automatically. Instead, the issuer of the request must construct and submit a new request, if so desired.”…””}”(hjXh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M©hj9h²hubjv)”}”(hŒÙNote that this timeout, in combination with packet transmission and acknowledgment timeouts, guarantees that the request layer will always make progress, even if only through timing out packets, and never fully block.”h]”hŒÙNote that this timeout, in combination with packet transmission and acknowledgment timeouts, guarantees that the request layer will always make progress, even if only through timing out packets, and never fully block.”…””}”(hjxh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M±hj9h²hubeh}”(h]”Œid2”ah ]”h"]”h$]”j? ah&]”uh1j`hj´h²hh³hÇh´M¢jE Kubja)”}”(hhh]”(jf)”}”(hŒConcurrency and Locking”h]”hŒConcurrency and Locking”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjh²hh³hÇh´M¶ubjv)”}”(hXSimilar to the packet transport layer, there are two main locks in the request transport layer: One guarding access to the request queue and one guarding access to the pending set. These collections may only be accessed and modified under the respective lock.”h]”hXSimilar to the packet transport layer, there are two main locks in the request transport layer: One guarding access to the request queue and one guarding access to the pending set. These collections may only be accessed and modified under the respective lock.”…””}”(hjžh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M¸hjh²hubjv)”}”(hXOther parts of the request transport layer are guarded independently. State flags are (again) managed by atomic bit operations and, if necessary, memory barriers. Modifications to the timeout reaper work item and expiration date are guarded by their own lock.”h]”hXOther parts of the request transport layer are guarded independently. State flags are (again) managed by atomic bit operations and, if necessary, memory barriers. Modifications to the timeout reaper work item and expiration date are guarded by their own lock.”…””}”(hj¬h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M½hjh²hubjv)”}”(hXSome request fields may be read outside of the respective locks guarding them, specifically the state for tracing. In those cases, proper access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``. Such read-only access is only allowed when stale values are not critical.”h]”(hŒ©Some request fields may be read outside of the respective locks guarding them, specifically the state for tracing. In those cases, proper access is ensured by employing ”…””}”(hjºh²hh³Nh´NubhÓ)”}”(hŒ``WRITE_ONCE()``”h]”hŒ WRITE_ONCE()”…””}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjºubhŒ and ”…””}”(hjºh²hh³Nh´NubhÓ)”}”(hŒ``READ_ONCE()``”h]”hŒ READ_ONCE()”…””}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhjºubhŒK. Such read-only access is only allowed when stale values are not critical.”…””}”(hjºh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MÂhjh²hubjv)”}”(hX¬With respect to the interface for higher layers, request submission (|ssh_rtl_submit|), request cancellation (|ssh_rtl_cancel|), and layer shutdown (|ssh_rtl_shutdown|) may always be executed concurrently with respect to each other. Note that request submission may not run concurrently with itself for the same request (and also may only be called once per request). Equally, shutdown may also not run concurrently with itself.”h]”(hŒEWith respect to the interface for higher layers, request submission (”…””}”(hjìh²hh³Nh´Nubh)”}”(hjÒh]”hÓ)”}”(hjÒh]”hŒssh_rtl_submit()”…””}”(hj÷h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÞeh"]”h$]”h&]”uh1hÒh³Nh´Nhjôubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jëŒ refexplicit”‰Œrefwarn”‰Œ reftarget”jîuh1hh³hÇh´K hjìh²hubhŒ), request cancellation (”…””}”(hjìh²hh³Nh´Nubh)”}”(hjüh]”hÓ)”}”(hjüh]”hŒssh_rtl_cancel()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjeh"]”h$]”h&]”uh1hÒh³Nh´Nhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jŒ refexplicit”‰Œrefwarn”‰Œ reftarget”juh1hh³hÇh´K hjìh²hubhŒ), and layer shutdown (”…””}”(hjìh²hh³Nh´Nubh)”}”(hj&h]”hÓ)”}”(hj&h]”hŒssh_rtl_shutdown()”…””}”(hj7h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj2eh"]”h$]”h&]”uh1hÒh³Nh´Nhj4ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j?Œ refexplicit”‰Œrefwarn”‰Œ reftarget”jBuh1hh³hÇh´K hjìh²hubhX) may always be executed concurrently with respect to each other. Note that request submission may not run concurrently with itself for the same request (and also may only be called once per request). Equally, shutdown may also not run concurrently with itself.”…””}”(hjìh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MÇhjh²hubeh}”(h]”Œid3”ah ]”h"]”h$]”jªah&]”uh1j`hj´h²hh³hÇh´M¶jE Kubeh}”(h]”Œrequest-transport-layer”ah ]”h"]”Œrequest transport layer”ah$]”h&]”uh1j`hjbh²hh³hÇh´M!ubja)”}”(hhh]”(jf)”}”(hŒController Layer”h]”hŒController Layer”…””}”(hjlh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjih²hh³hÇh´MÐubjv)”}”(hXüThe controller layer extends on the request transport layer to provide an easy-to-use interface for client drivers. It is represented by |ssam_controller| and the SSH driver. While the lower level transport layers take care of transmitting and handling packets and requests, the controller layer takes on more of a management role. Specifically, it handles device initialization, power management, and event handling, including event delivery and registration via the (event) completion system (|ssam_cplt|).”h]”(hŒ‰The controller layer extends on the request transport layer to provide an easy-to-use interface for client drivers. It is represented by ”…””}”(hjzh²hh³Nh´Nubh)”}”(hjÆh]”hÓ)”}”(hjÆh]”hŒstruct ssam_controller”…””}”(hj…h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÒeh"]”h$]”h&]”uh1hÒh³Nh´Nhj‚ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jߌ refexplicit”ˆŒrefwarn”‰Œ reftarget”jâuh1hh³hÇh´Khjzh²hubhXU and the SSH driver. While the lower level transport layers take care of transmitting and handling packets and requests, the controller layer takes on more of a management role. Specifically, it handles device initialization, power management, and event handling, including event delivery and registration via the (event) completion system (”…””}”(hjzh²hh³Nh´Nubh)”}”(hjèh]”hÓ)”}”(hjèh]”hŒstruct ssam_cplt”…””}”(hj¥h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjôeh"]”h$]”h&]”uh1hÒh³Nh´Nhj¢ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”juh1hh³hÇh´K(hjzh²hubhŒ).”…””}”(hjzh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MÒhjih²hubja)”}”(hhh]”(jf)”}”(hŒEvent Registration”h]”hŒEvent Registration”…””}”(hjËh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjÈh²hh³hÇh´MÛubjv)”}”(hX*In general, an event (or rather a class of events) has to be explicitly requested by the host before the EC will send it (HID input events seem to be the exception). This is done via an event-enable request (similarly, events should be disabled via an event-disable request once no longer desired).”h]”hX*In general, an event (or rather a class of events) has to be explicitly requested by the host before the EC will send it (HID input events seem to be the exception). This is done via an event-enable request (similarly, events should be disabled via an event-disable request once no longer desired).”…””}”(hjÙh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MÝhjÈh²hubjv)”}”(hX_The specific request used to enable (or disable) an event is given via an event registry, i.e. the governing authority of this event (so to speak), represented by |ssam_event_registry|. As parameters to this request, the target category and, depending on the event registry, instance ID of the event to be enabled must be provided. This (optional) instance ID must be zero if the registry does not use it. Together, target category and instance ID form the event ID, represented by |ssam_event_id|. In short, both, event registry and event ID, are required to uniquely identify a respective class of events.”h]”(hŒ£The specific request used to enable (or disable) an event is given via an event registry, i.e. the governing authority of this event (so to speak), represented by ”…””}”(hjçh²hh³Nh´Nubh)”}”(hjÂh]”hÓ)”}”(hjÂh]”hŒstruct ssam_event_registry”…””}”(hjòh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÎeh"]”h$]”h&]”uh1hÒh³Nh´Nhjïubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jÛŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”jÞuh1hh³hÇh´K!hjçh²hubhX*. As parameters to this request, the target category and, depending on the event registry, instance ID of the event to be enabled must be provided. This (optional) instance ID must be zero if the registry does not use it. Together, target category and instance ID form the event ID, represented by ”…””}”(hjçh²hh³Nh´Nubh)”}”(hjìh]”hÓ)”}”(hjìh]”hŒstruct ssam_event_id”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjøeh"]”h$]”h&]”uh1hÒh³Nh´Nhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”juh1hh³hÇh´K"hjçh²hubhŒn. In short, both, event registry and event ID, are required to uniquely identify a respective class of events.”…””}”(hjçh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MãhjÈh²hubjv)”}”(hX'Note that a further *request ID* parameter must be provided for the enable-event request. This parameter does not influence the class of events being enabled, but instead is set as the request ID (RQID) on each event of this class sent by the EC. It is used to identify events (as a limited number of request IDs is reserved for use in events only, specifically one to ``SSH_NUM_EVENTS`` inclusively) and also map events to their specific class. Currently, the controller always sets this parameter to the target category specified in |ssam_event_id|.”h]”(hŒNote that a further ”…””}”(hj5h²hh³Nh´NubjÓ)”}”(hŒ *request ID*”h]”hŒ request ID”…””}”(hj=h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj5ubhXQ parameter must be provided for the enable-event request. This parameter does not influence the class of events being enabled, but instead is set as the request ID (RQID) on each event of this class sent by the EC. It is used to identify events (as a limited number of request IDs is reserved for use in events only, specifically one to ”…””}”(hj5h²hh³Nh´NubhÓ)”}”(hŒ``SSH_NUM_EVENTS``”h]”hŒSSH_NUM_EVENTS”…””}”(hjOh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj5ubhŒ” inclusively) and also map events to their specific class. Currently, the controller always sets this parameter to the target category specified in ”…””}”(hj5h²hh³Nh´Nubh)”}”(hjìh]”hÓ)”}”(hjìh]”hŒstruct ssam_event_id”…””}”(hjdh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjøeh"]”h$]”h&]”uh1hÒh³Nh´Nhjaubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jŒ refexplicit”ˆŒrefwarn”‰Œ reftarget”juh1hh³hÇh´K"hj5h²hubhŒ.”…””}”(hj5h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MíhjÈh²hubjv)”}”(hX×As multiple client drivers may rely on the same (or overlapping) classes of events and enable/disable calls are strictly binary (i.e. on/off), the controller has to manage access to these events. It does so via reference counting, storing the counter inside an RB-tree based mapping with event registry and ID as key (there is no known list of valid event registry and event ID combinations). See |ssam_nf|, |ssam_nf_refcount_inc|, and |ssam_nf_refcount_dec| for details.”h]”(hXAs multiple client drivers may rely on the same (or overlapping) classes of events and enable/disable calls are strictly binary (i.e. on/off), the controller has to manage access to these events. It does so via reference counting, storing the counter inside an RB-tree based mapping with event registry and ID as key (there is no known list of valid event registry and event ID combinations). See ”…””}”(hj‡h²hh³Nh´Nubh)”}”(hjh]”hÓ)”}”(hjh]”hŒstruct ssam_nf”…””}”(hj’h²hh³Nh´Nubah}”(h]”h ]”(hÞhßj"eh"]”h$]”h&]”uh1hÒh³Nh´Nhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j/Œ refexplicit”ˆŒrefwarn”‰Œ reftarget”j2uh1hh³hÇh´K#hj‡h²hubhŒ, ”…””}”(hj‡h²hh³Nh´Nubh)”}”(hj@h]”hÓ)”}”(hj@h]”hŒssam_nf_refcount_inc()”…””}”(hj²h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjLeh"]”h$]”h&]”uh1hÒh³Nh´Nhj¯ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jYŒ refexplicit”‰Œrefwarn”‰Œ reftarget”j\uh1hh³hÇh´K$hj‡h²hubhŒ, and ”…””}”(hj‡h²hh³Nh´Nubh)”}”(hjjh]”hÓ)”}”(hjjh]”hŒssam_nf_refcount_dec()”…””}”(hjÒh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjveh"]”h$]”h&]”uh1hÒh³Nh´NhjÏubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jƒŒ refexplicit”‰Œrefwarn”‰Œ reftarget”j†uh1hh³hÇh´K%hj‡h²hubhŒ for details.”…””}”(hj‡h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MöhjÈh²hubjv)”}”(hŒ°This management is done together with notifier registration (described in the next section) via the top-level |ssam_notifier_register| and |ssam_notifier_unregister| functions.”h]”(hŒnThis management is done together with notifier registration (described in the next section) via the top-level ”…””}”(hjõh²hh³Nh´Nubh)”}”(hj”h]”hÓ)”}”(hj”h]”hŒssam_notifier_register()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj eh"]”h$]”h&]”uh1hÒh³Nh´Nhjýubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j­Œ refexplicit”‰Œrefwarn”‰Œ reftarget”j°uh1hh³hÇh´K&hjõh²hubhŒ and ”…””}”(hjõh²hh³Nh´Nubh)”}”(hj¾h]”hÓ)”}”(hj¾h]”hŒssam_notifier_unregister()”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÊeh"]”h$]”h&]”uh1hÒh³Nh´Nhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j׌ refexplicit”‰Œrefwarn”‰Œ reftarget”jÚuh1hh³hÇh´K'hjõh²hubhŒ functions.”…””}”(hjõh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MþhjÈh²hubeh}”(h]”Œevent-registration”ah ]”h"]”Œevent registration”ah$]”h&]”uh1j`hjih²hh³hÇh´MÛubja)”}”(hhh]”(jf)”}”(hŒEvent Delivery”h]”hŒEvent Delivery”…””}”(hjNh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjKh²hh³hÇh´Mubjv)”}”(hX@To receive events, a client driver has to register an event notifier via |ssam_notifier_register|. This increments the reference counter for that specific class of events (as detailed in the previous section), enables the class on the EC (if it has not been enabled already), and installs the provided notifier callback.”h]”(hŒITo receive events, a client driver has to register an event notifier via ”…””}”(hj\h²hh³Nh´Nubh)”}”(hj”h]”hÓ)”}”(hj”h]”hŒssam_notifier_register()”…””}”(hjgh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj eh"]”h$]”h&]”uh1hÒh³Nh´Nhjdubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j­Œ refexplicit”‰Œrefwarn”‰Œ reftarget”j°uh1hh³hÇh´K&hj\h²hubhŒß. This increments the reference counter for that specific class of events (as detailed in the previous section), enables the class on the EC (if it has not been enabled already), and installs the provided notifier callback.”…””}”(hj\h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MhjKh²hubjv)”}”(hX¯Notifier callbacks are stored in lists, with one (RCU) list per target category (provided via the event ID; NB: there is a fixed known number of target categories). There is no known association from the combination of event registry and event ID to the command data (target ID, target category, command ID, and instance ID) that can be provided by an event class, apart from target category and instance ID given via the event ID.”h]”hX¯Notifier callbacks are stored in lists, with one (RCU) list per target category (provided via the event ID; NB: there is a fixed known number of target categories). There is no known association from the combination of event registry and event ID to the command data (target ID, target category, command ID, and instance ID) that can be provided by an event class, apart from target category and instance ID given via the event ID.”…””}”(hjŠh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M hjKh²hubjv)”}”(hXNote that due to the way notifiers are (or rather have to be) stored, client drivers may receive events that they have not requested and need to account for them. Specifically, they will, by default, receive all events from the same target category. To simplify dealing with this, filtering of events by target ID (provided via the event registry) and instance ID (provided via the event ID) can be requested when registering a notifier. This filtering is applied when iterating over the notifiers at the time they are executed.”h]”hXNote that due to the way notifiers are (or rather have to be) stored, client drivers may receive events that they have not requested and need to account for them. Specifically, they will, by default, receive all events from the same target category. To simplify dealing with this, filtering of events by target ID (provided via the event registry) and instance ID (provided via the event ID) can be requested when registering a notifier. This filtering is applied when iterating over the notifiers at the time they are executed.”…””}”(hj˜h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MhjKh²hubjv)”}”(hX All notifier callbacks are executed on a dedicated workqueue, the so-called completion workqueue. After an event has been received via the callback installed in the request layer (running on the receiver thread of the packet transport layer), it will be put on its respective event queue (|ssam_event_queue|). From this event queue the completion work item of that queue (running on the completion workqueue) will pick up the event and execute the notifier callback. This is done to avoid blocking on the receiver thread.”h]”(hX!All notifier callbacks are executed on a dedicated workqueue, the so-called completion workqueue. After an event has been received via the callback installed in the request layer (running on the receiver thread of the packet transport layer), it will be put on its respective event queue (”…””}”(hj¦h²hh³Nh´Nubh)”}”(hjh]”hÓ)”}”(hjh]”hŒstruct ssam_event_queue”…””}”(hj±h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjeh"]”h$]”h&]”uh1hÒh³Nh´Nhj®ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j+Œ refexplicit”ˆŒrefwarn”‰Œ reftarget”j.uh1hh³hÇh´K)hj¦h²hubhŒÖ). From this event queue the completion work item of that queue (running on the completion workqueue) will pick up the event and execute the notifier callback. This is done to avoid blocking on the receiver thread.”…””}”(hj¦h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´MhjKh²hubjv)”}”(hX8There is one event queue per combination of target ID and target category. This is done to ensure that notifier callbacks are executed in sequence for events of the same target ID and target category. Callbacks can be executed in parallel for events with a different combination of target ID and target category.”h]”hX8There is one event queue per combination of target ID and target category. This is done to ensure that notifier callbacks are executed in sequence for events of the same target ID and target category. Callbacks can be executed in parallel for events with a different combination of target ID and target category.”…””}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M#hjKh²hubeh}”(h]”Œevent-delivery”ah ]”h"]”Œevent delivery”ah$]”h&]”uh1j`hjih²hh³hÇh´Mubja)”}”(hhh]”(jf)”}”(hŒConcurrency and Locking”h]”hŒConcurrency and Locking”…””}”(hjíh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jehjêh²hh³hÇh´M*ubjv)”}”(hŒÅMost of the concurrency related safety guarantees of the controller are provided by the lower-level request transport layer. In addition to this, event (un-)registration is guarded by its own lock.”h]”hŒÅMost of the concurrency related safety guarantees of the controller are provided by the lower-level request transport layer. In addition to this, event (un-)registration is guarded by its own lock.”…””}”(hjûh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M,hjêh²hubjv)”}”(hXCAccess to the controller state is guarded by the state lock. This lock is a read/write semaphore. The reader part can be used to ensure that the state does not change while functions depending on the state to stay the same (e.g. |ssam_notifier_register|, |ssam_notifier_unregister|, |ssam_request_sync_submit|, and derivatives) are executed and this guarantee is not already provided otherwise (e.g. through |ssam_client_bind| or |ssam_client_link|). The writer part guards any transitions that will change the state, i.e. initialization, destruction, suspension, and resumption.”h]”(hŒåAccess to the controller state is guarded by the state lock. This lock is a read/write semaphore. The reader part can be used to ensure that the state does not change while functions depending on the state to stay the same (e.g. ”…””}”(hj h²hh³Nh´Nubh)”}”(hj”h]”hÓ)”}”(hj”h]”hŒssam_notifier_register()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj eh"]”h$]”h&]”uh1hÒh³Nh´Nhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j­Œ refexplicit”‰Œrefwarn”‰Œ reftarget”j°uh1hh³hÇh´K&hj h²hubhŒ, ”…””}”(hj h²hh³Nh´Nubh)”}”(hj¾h]”hÓ)”}”(hj¾h]”hŒssam_notifier_unregister()”…””}”(hj4h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÊeh"]”h$]”h&]”uh1hÒh³Nh´Nhj1ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j׌ refexplicit”‰Œrefwarn”‰Œ reftarget”jÚuh1hh³hÇh´K'hj h²hubhŒ, ”…””}”(hj h²hh³Nh´Nubh)”}”(hj<h]”hÓ)”}”(hj<h]”hŒssam_request_sync_submit()”…””}”(hjTh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjHeh"]”h$]”h&]”uh1hÒh³Nh´NhjQubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jUŒ refexplicit”‰Œrefwarn”‰Œ reftarget”jXuh1hh³hÇh´K*hj h²hubhŒc, and derivatives) are executed and this guarantee is not already provided otherwise (e.g. through ”…””}”(hj h²hh³Nh´Nubh)”}”(hjDh]”hÓ)”}”(hjDh]”hŒssam_client_bind()”…””}”(hjth²hh³Nh´Nubah}”(h]”h ]”(hÞhßjPeh"]”h$]”h&]”uh1hÒh³Nh´Nhjqubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j]Œ refexplicit”‰Œrefwarn”‰Œ reftarget”j`uh1hh³hÇh´Khj h²hubhŒ or ”…””}”(hj h²hh³Nh´Nubh)”}”(hjnh]”hÓ)”}”(hjnh]”hŒssam_client_link()”…””}”(hj”h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjzeh"]”h$]”h&]”uh1hÒh³Nh´Nhj‘ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j‡Œ refexplicit”‰Œrefwarn”‰Œ reftarget”jŠuh1hh³hÇh´Khj h²hubhŒƒ). The writer part guards any transitions that will change the state, i.e. initialization, destruction, suspension, and resumption.”…””}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M0hjêh²hubjv)”}”(hX~The controller state may be accessed (read-only) outside the state lock for smoke-testing against invalid API usage (e.g. in |ssam_request_sync_submit|). Note that such checks are not supposed to (and will not) protect against all invalid usages, but rather aim to help catch them. In those cases, proper variable access is ensured by employing ``WRITE_ONCE()`` and ``READ_ONCE()``.”h]”(hŒ}The controller state may be accessed (read-only) outside the state lock for smoke-testing against invalid API usage (e.g. in ”…””}”(hj·h²hh³Nh´Nubh)”}”(hj<h]”hÓ)”}”(hj<h]”hŒssam_request_sync_submit()”…””}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjHeh"]”h$]”h&]”uh1hÒh³Nh´Nhj¿ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jUŒ refexplicit”‰Œrefwarn”‰Œ reftarget”jXuh1hh³hÇh´K*hj·h²hubhŒÂ). Note that such checks are not supposed to (and will not) protect against all invalid usages, but rather aim to help catch them. In those cases, proper variable access is ensured by employing ”…””}”(hj·h²hh³Nh´NubhÓ)”}”(hŒ``WRITE_ONCE()``”h]”hŒ WRITE_ONCE()”…””}”(hjßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj·ubhŒ and ”…””}”(hj·h²hh³Nh´NubhÓ)”}”(hŒ``READ_ONCE()``”h]”hŒ READ_ONCE()”…””}”(hjñh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÒhj·ubhŒ.”…””}”(hj·h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M9hjêh²hubjv)”}”(hX4Assuming any preconditions on the state not changing have been satisfied, all non-initialization and non-shutdown functions may run concurrently with each other. This includes |ssam_notifier_register|, |ssam_notifier_unregister|, |ssam_request_sync_submit|, as well as all functions building on top of those.”h]”(hŒ°Assuming any preconditions on the state not changing have been satisfied, all non-initialization and non-shutdown functions may run concurrently with each other. This includes ”…””}”(hj h²hh³Nh´Nubh)”}”(hj”h]”hÓ)”}”(hj”h]”hŒssam_notifier_register()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(hÞhßj eh"]”h$]”h&]”uh1hÒh³Nh´Nhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j­Œ refexplicit”‰Œrefwarn”‰Œ reftarget”j°uh1hh³hÇh´K&hj h²hubhŒ, ”…””}”(hj h²hh³Nh´Nubh)”}”(hj¾h]”hÓ)”}”(hj¾h]”hŒssam_notifier_unregister()”…””}”(hj4h²hh³Nh´Nubah}”(h]”h ]”(hÞhßjÊeh"]”h$]”h&]”uh1hÒh³Nh´Nhj1ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”j׌ refexplicit”‰Œrefwarn”‰Œ reftarget”jÚuh1hh³hÇh´K'hj h²hubhŒ, ”…””}”(hj h²hh³Nh´Nubh)”}”(hj<h]”hÓ)”}”(hj<h]”hŒssam_request_sync_submit()”…””}”(hjTh²hh³Nh´Nubah}”(h]”h ]”(hÞhßjHeh"]”h$]”h&]”uh1hÒh³Nh´NhjQubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”hëŒ refdomain”hߌreftype”jUŒ refexplicit”‰Œrefwarn”‰Œ reftarget”jXuh1hh³hÇh´K*hj h²hubhŒ4, as well as all functions building on top of those.”…””}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1juh³hÇh´M?hjêh²hubeh}”(h]”Œid4”ah ]”h"]”h$]”Œconcurrency and locking”ah&]”uh1j`hjih²hh³hÇh´M*jE Kubeh}”(h]”Œcontroller-layer”ah ]”h"]”Œcontroller layer”ah$]”h&]”uh1j`hjbh²hh³hÇh´MÐubeh}”(h]”Œcore-driver-internals”ah ]”h"]”Œcore driver internals”ah$]”h&]”uh1j`hhh²hh³hÇh´K.ubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(jeNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j²Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÇŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”(h÷hÊj!hújKj$jujNjŸjxjÉj¢jójÌjjöjGj jqjJj›jtjÅjžjïjÈjjòjCjjmjFj—jpjÁjšjëjÄjjîj?jjijBj“jlj½j–jçjÀjjêj;jjej>jjhj¹j’jãj¼j jæj7jjaj:j‹jdjµjŽjßj¸j jâj3j j]j6uŒsubstitution_names”}”(Œssh_ptl”h÷Œssh_ptl_submit”j!Œssh_ptl_cancel”jKŒssh_ptl_shutdown”juŒssh_ptl_rx_rcvbuf”jŸŒssh_rtl”jÉŒssh_rtl_submit”jóŒssh_rtl_cancel”jŒssh_rtl_shutdown”jGŒ ssh_packet”jqŒssh_packet_get”j›Œssh_packet_put”jÅŒssh_packet_ops”jïŒssh_packet_base_priority”jŒssh_packet_flags”jCŒssh_packet_priority”jmŒ ssh_frame”j—Œ ssh_command”jÁŒ ssh_request”jëŒssh_request_get”jŒssh_request_put”j?Œssh_request_ops”jiŒssh_request_init”j“Œssh_request_flags”j½Œssam_controller”jçŒ ssam_device”jŒssam_device_driver”j;Œssam_client_bind”jeŒssam_client_link”jŒssam_request_sync”j¹Œssam_event_registry”j㌠ssam_event_id”j Œssam_nf”j7Œssam_nf_refcount_inc”jaŒssam_nf_refcount_dec”j‹Œssam_notifier_register”jµŒssam_notifier_unregister”jߌ ssam_cplt”j Œssam_event_queue”j3Œssam_request_sync_submit”j]uŒrefnames”}”Œrefids”}”Œnameids”}”(jŒj‰jÃjÀj±j®j˜ j• j j Œ pending set”Njx ju jÛ jØ Œtimeout reaper”NŒconcurrency and locking”Njfjcjjjmjjjºj·jïjìj6j3j„jjHjEjçjäuŒ nametypes”}”(jŒ‰jÉj±‰j˜ ‰j ‰j‰jx ‰jÛ ‰j‰j ‰jf‰j‰jm‰jº‰jï‰j6‰j„‰jH‰jç‰uh}”(j‰jbjÀj«j®jÆj• j j j› j? j ju jF jØ j{ j; jÞ j¦jA jcj´jj3jjjj‘jpj·j–jìj½j3jòjˆj9j\jjjijEjÈjäjKjyjêuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”jÀKs…”R”Œparse_messages”]”(hŒsystem_message”“”)”}”(hhh]”jv)”}”(hŒ.Duplicate implicit target name: "pending set".”h]”hŒ2Duplicate implicit target name: “pending setâ€.”…””}”(hjDh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juhjAubah}”(h]”h ]”h"]”h$]”h&]”j‘aŒlevel”KŒtype”ŒINFO”Œsource”hÇŒline”Mtuh1j?hjph²hh³hÇh´Mtubj@)”}”(hhh]”jv)”}”(hŒ1Duplicate implicit target name: "timeout reaper".”h]”hŒ5Duplicate implicit target name: “timeout reaperâ€.”…””}”(hj`h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juhj]ubah}”(h]”h ]”h"]”h$]”h&]”jˆaŒlevel”KŒtype”jZŒsource”hÇŒline”M¢uh1j?hj9h²hh³hÇh´M¢ubj@)”}”(hhh]”jv)”}”(hŒ:Duplicate implicit target name: "concurrency and locking".”h]”hŒ>Duplicate implicit target name: “concurrency and lockingâ€.”…””}”(hj{h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juhjxubah}”(h]”h ]”h"]”h$]”h&]”j\aŒlevel”KŒtype”jZŒsource”hÇŒline”M¶uh1j?hjh²hh³hÇh´M¶ubj@)”}”(hhh]”jv)”}”(hŒ:Duplicate implicit target name: "concurrency and locking".”h]”hŒ>Duplicate implicit target name: “concurrency and lockingâ€.”…””}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1juhj“ubah}”(h]”h ]”h"]”h$]”h&]”jyaŒlevel”KŒtype”jZŒsource”hÇŒline”M*uh1j?hjêh²hh³hÇh´M*ubeŒtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.