€•DNŒ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/networking/driver”Œ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/networking/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/it_IT/networking/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/ja_JP/networking/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/ko_KR/networking/driver”Œ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/networking/driver”Œ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/networking/driver”Œ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³Œ?/var/lib/git/docbuild/linux/Documentation/networking/driver.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒSoftnet Driver Issues”h]”hŒSoftnet Driver Issues”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒProbing guidelines”h]”hŒProbing guidelines”…””}”(hhàh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÝh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒAddress validation”h]”hŒAddress validation”…””}”(hhñh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhîh²hh³hÇh´K ubhŒ paragraph”“”)”}”(hŒœAny hardware layer address you obtain for your device should be verified. For example, for ethernet check it with linux/etherdevice.h:is_valid_ether_addr()”h]”hŒœAny hardware layer address you obtain for your device should be verified. For example, for ethernet check it with linux/etherdevice.h:is_valid_ether_addr()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´K hhîh²hubeh}”(h]”Œaddress-validation”ah ]”h"]”Œaddress validation”ah$]”h&]”uh1hÈhhÝh²hh³hÇh´K ubeh}”(h]”Œprobing-guidelines”ah ]”h"]”Œprobing guidelines”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒClose/stop guidelines”h]”hŒClose/stop guidelines”…””}”(hj"h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒ Quiescence”h]”hŒ Quiescence”…””}”(hj3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj0h²hh³hÇh´Kubj)”}”(hŒÈAfter the ndo_stop routine has been called, the hardware must not receive or transmit any data. All in flight packets must be aborted. If necessary, poll or wait for completion of any reset commands.”h]”hŒÈAfter the ndo_stop routine has been called, the hardware must not receive or transmit any data. All in flight packets must be aborted. If necessary, poll or wait for completion of any reset commands.”…””}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´Khj0h²hubeh}”(h]”Œ quiescence”ah ]”h"]”Œ quiescence”ah$]”h&]”uh1hÈhjh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒ Auto-close”h]”hŒ Auto-close”…””}”(hjZh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjWh²hh³hÇh´Kubj)”}”(hŒRThe ndo_stop routine will be called by unregister_netdevice if device is still UP.”h]”hŒRThe ndo_stop routine will be called by unregister_netdevice if device is still UP.”…””}”(hjhh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´KhjWh²hubeh}”(h]”Œ auto-close”ah ]”h"]”Œ auto-close”ah$]”h&]”uh1hÈhjh²hh³hÇh´Kubeh}”(h]”Œclose-stop-guidelines”ah ]”h"]”Œclose/stop guidelines”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒTransmit path guidelines”h]”hŒTransmit path guidelines”…””}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj†h²hh³hÇh´K#ubhÉ)”}”(hhh]”(hÎ)”}”(hŒStop queues in advance”h]”hŒStop queues in advance”…””}”(hjšh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj—h²hh³hÇh´K&ubj)”}”(hŒÞThe ndo_start_xmit method must not return NETDEV_TX_BUSY under any normal circumstances. It is considered a hard error unless there is no way your device can tell ahead of time when its transmit function will become busy.”h]”hŒÞThe ndo_start_xmit method must not return NETDEV_TX_BUSY under any normal circumstances. It is considered a hard error unless there is no way your device can tell ahead of time when its transmit function will become busy.”…””}”(hj¨h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´K(hj—h²hubj)”}”(hŒoInstead it must maintain the queue properly. For example, for a driver implementing scatter-gather this means:”h]”hŒoInstead it must maintain the queue properly. For example, for a driver implementing scatter-gather this means:”…””}”(hj¶h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´K-hj—h²hubhŒ literal_block”“”)”}”(hX±static u32 drv_tx_avail(struct drv_ring *dr) { u32 used = READ_ONCE(dr->prod) - READ_ONCE(dr->cons); return dr->tx_ring_size - (used & dr->tx_ring_mask); } static netdev_tx_t drv_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct drv *dp = netdev_priv(dev); struct netdev_queue *txq; struct drv_ring *dr; int idx; idx = skb_get_queue_mapping(skb); dr = dp->tx_rings[idx]; txq = netdev_get_tx_queue(dev, idx); //... /* This should be a very rare race - log it. */ if (drv_tx_avail(dr) <= skb_shinfo(skb)->nr_frags + 1) { netif_tx_stop_queue(txq); netdev_warn(dev, "Tx Ring full when queue awake!\n"); return NETDEV_TX_BUSY; } //... queue packet to card ... netdev_tx_sent_queue(txq, skb->len); //... update tx producer index using WRITE_ONCE() ... if (!netif_txq_maybe_stop(txq, drv_tx_avail(dr), MAX_SKB_FRAGS + 1, 2 * MAX_SKB_FRAGS)) dr->stats.stopped++; //... return NETDEV_TX_OK; }”h]”hX±static u32 drv_tx_avail(struct drv_ring *dr) { u32 used = READ_ONCE(dr->prod) - READ_ONCE(dr->cons); return dr->tx_ring_size - (used & dr->tx_ring_mask); } static netdev_tx_t drv_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct drv *dp = netdev_priv(dev); struct netdev_queue *txq; struct drv_ring *dr; int idx; idx = skb_get_queue_mapping(skb); dr = dp->tx_rings[idx]; txq = netdev_get_tx_queue(dev, idx); //... /* This should be a very rare race - log it. */ if (drv_tx_avail(dr) <= skb_shinfo(skb)->nr_frags + 1) { netif_tx_stop_queue(txq); netdev_warn(dev, "Tx Ring full when queue awake!\n"); return NETDEV_TX_BUSY; } //... queue packet to card ... netdev_tx_sent_queue(txq, skb->len); //... update tx producer index using WRITE_ONCE() ... if (!netif_txq_maybe_stop(txq, drv_tx_avail(dr), MAX_SKB_FRAGS + 1, 2 * MAX_SKB_FRAGS)) dr->stats.stopped++; //... return NETDEV_TX_OK; }”…””}”hjÆsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆŒforce”‰Œlanguage”Œc”Œhighlight_args”}”uh1jÄh³hÇh´K0hj—h²hubj)”}”(hŒ:And then at the end of your TX reclamation event handling:”h]”hŒ:And then at the end of your TX reclamation event handling:”…””}”(hjÙh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´K[hj—h²hubjÅ)”}”(hŒª//... update tx consumer index using WRITE_ONCE() ... netif_txq_completed_wake(txq, cmpl_pkts, cmpl_bytes, drv_tx_avail(dr), 2 * MAX_SKB_FRAGS);”h]”hŒª//... update tx consumer index using WRITE_ONCE() ... netif_txq_completed_wake(txq, cmpl_pkts, cmpl_bytes, drv_tx_avail(dr), 2 * MAX_SKB_FRAGS);”…””}”hjçsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆjÔ‰jÕjÖj×}”uh1jÄh³hÇh´K]hj—h²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒ(Lockless queue stop / wake helper macros”h]”hŒ(Lockless queue stop / wake helper macros”…””}”(hjùh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjöh²hh³hÇh´Keubj)”}”(hŒ£The netif_txq_maybe_stop() and __netif_txq_completed_wake() macros are designed to safely implement stopping and waking netdev queues without full lock protection.”h]”hŒ£The netif_txq_maybe_stop() and __netif_txq_completed_wake() macros are designed to safely implement stopping and waking netdev queues without full lock protection.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³Œ^/var/lib/git/docbuild/linux/Documentation/networking/driver:103: ./include/net/netdev_queues.h”h´KÆhjöh²hubj)”}”(hXWe assume that there can be no concurrent stop attempts and no concurrent wake attempts. The try-stop should happen from the xmit handler, while wake up should be triggered from NAPI poll context. The two may run concurrently (single producer, single consumer).”h]”hXWe assume that there can be no concurrent stop attempts and no concurrent wake attempts. The try-stop should happen from the xmit handler, while wake up should be triggered from NAPI poll context. The two may run concurrently (single producer, single consumer).”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³Œ^/var/lib/git/docbuild/linux/Documentation/networking/driver:103: ./include/net/netdev_queues.h”h´KÊhjöh²hubj)”}”(hXCThe try-stop side is expected to run from the xmit handler and therefore it does not reschedule Tx (netif_tx_start_queue() instead of netif_tx_wake_queue()). Uses of the ``stop`` macros outside of the xmit handler may lead to xmit queue being enabled but not run. The waking side does not have similar context restrictions.”h]”(hŒªThe try-stop side is expected to run from the xmit handler and therefore it does not reschedule Tx (netif_tx_start_queue() instead of netif_tx_wake_queue()). Uses of the ”…””}”(hj%h²hh³Nh´NubhŒliteral”“”)”}”(hŒ``stop``”h]”hŒstop”…””}”(hj/h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj%ubhŒ‘ macros outside of the xmit handler may lead to xmit queue being enabled but not run. The waking side does not have similar context restrictions.”…””}”(hj%h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³Œ^/var/lib/git/docbuild/linux/Documentation/networking/driver:103: ./include/net/netdev_queues.h”h´KÏhjöh²hubj)”}”(hŒÙThe macros guarantee that rings will not remain stopped if there's space available, but they do *not* prevent false wake ups when the ring is full! Drivers should check for ring full at the start for the xmit handler.”h]”(hŒbThe macros guarantee that rings will not remain stopped if there’s space available, but they do ”…””}”(hjHh²hh³Nh´NubhŒemphasis”“”)”}”(hŒ*not*”h]”hŒnot”…””}”(hjRh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jPhjHubhŒt prevent false wake ups when the ring is full! Drivers should check for ring full at the start for the xmit handler.”…””}”(hjHh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³Œ^/var/lib/git/docbuild/linux/Documentation/networking/driver:103: ./include/net/netdev_queues.h”h´KÕhjöh²hubj)”}”(hŒiAll descriptor ring indexes (and other relevant shared state) must be updated before invoking the macros.”h]”hŒiAll descriptor ring indexes (and other relevant shared state) must be updated before invoking the macros.”…””}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³Œ^/var/lib/git/docbuild/linux/Documentation/networking/driver:103: ./include/net/netdev_queues.h”h´KÚhjöh²hubj)”}”(hŒ‹The standard macros like netif_txq_maybe_stop(), netif_txq_try_stop() etc. are well tested, prefer them over local synchronization schemes.”h]”hŒ‹The standard macros like netif_txq_maybe_stop(), netif_txq_try_stop() etc. are well tested, prefer them over local synchronization schemes.”…””}”(hjzh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´Kjhjöh²hubeh}”(h]”Œ&lockless-queue-stop-wake-helper-macros”ah ]”h"]”Œ(lockless queue stop / wake helper macros”ah$]”h&]”uh1hÈhj—h²hh³hÇh´Keubeh}”(h]”Œstop-queues-in-advance”ah ]”h"]”Œstop queues in advance”ah$]”h&]”uh1hÈhj†h²hh³hÇh´K&ubhÉ)”}”(hhh]”(hÎ)”}”(hŒNo exclusive ownership”h]”hŒNo exclusive ownership”…””}”(hj›h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj˜h²hh³hÇh´Knubj)”}”(hŒJAn ndo_start_xmit method must not modify the shared parts of a cloned SKB.”h]”hŒJAn ndo_start_xmit method must not modify the shared parts of a cloned SKB.”…””}”(hj©h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´Kphj˜h²hubeh}”(h]”Œno-exclusive-ownership”ah ]”h"]”Œno exclusive ownership”ah$]”h&]”uh1hÈhj†h²hh³hÇh´KnubhÉ)”}”(hhh]”(hÎ)”}”(hŒTimely completions”h]”hŒTimely completions”…””}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj¿h²hh³hÇh´Ktubj)”}”(hŒ©Do not forget that once you return NETDEV_TX_OK from your ndo_start_xmit method, it is your driver's responsibility to free up the SKB and in some finite amount of time.”h]”hŒ«Do not forget that once you return NETDEV_TX_OK from your ndo_start_xmit method, it is your driver’s responsibility to free up the SKB and in some finite amount of time.”…””}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´Kvhj¿h²hubj)”}”(hŒøFor example, this means that it is not allowed for your TX mitigation scheme to let TX packets "hang out" in the TX ring unreclaimed forever if no new TX packets are sent. This error can deadlock sockets waiting for send buffer room to be freed up.”h]”hŒüFor example, this means that it is not allowed for your TX mitigation scheme to let TX packets “hang out†in the TX ring unreclaimed forever if no new TX packets are sent. This error can deadlock sockets waiting for send buffer room to be freed up.”…””}”(hjÞh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´Kzhj¿h²hubj)”}”(hŒIf you return NETDEV_TX_BUSY from the ndo_start_xmit method, you must not keep any reference to that SKB and you must not attempt to free it up.”h]”hŒIf you return NETDEV_TX_BUSY from the ndo_start_xmit method, you must not keep any reference to that SKB and you must not attempt to free it up.”…””}”(hjìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´K€hj¿h²hubeh}”(h]”Œtimely-completions”ah ]”h"]”Œtimely completions”ah$]”h&]”uh1hÈhj†h²hh³hÇh´Ktubeh}”(h]”Œtransmit-path-guidelines”ah ]”h"]”Œtransmit path guidelines”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K#ubhÉ)”}”(hhh]”(hÎ)”}”(hŒError message reporting”h]”hŒError message reporting”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj h²hh³hÇh´K…ubj)”}”(hX„A number of driver configuration interfaces pass a Netlink extended ACK (``extack``) object to the driver (either directly as an argument or as a member of a parameter struct). The drivers should try to report most errors via the ``extack`` object. System level exceptions, indicating that system or device is misbehaving or is in bad state, should continue to be reported to system logs.”h]”(hŒIA number of driver configuration interfaces pass a Netlink extended ACK (”…””}”(hjh²hh³Nh´Nubj.)”}”(hŒ ``extack``”h]”hŒextack”…””}”(hj#h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjubhŒ“) object to the driver (either directly as an argument or as a member of a parameter struct). The drivers should try to report most errors via the ”…””}”(hjh²hh³Nh´Nubj.)”}”(hŒ ``extack``”h]”hŒextack”…””}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjubhŒ” object. System level exceptions, indicating that system or device is misbehaving or is in bad state, should continue to be reported to system logs.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´K‡hj h²hubj)”}”(hŒ‰Messages should be passed **either** via ``extack`` **or** to system logs. Drivers should not try to report the same information to both.”h]”(hŒMessages should be passed ”…””}”(hjMh²hh³Nh´NubhŒstrong”“”)”}”(hŒ **either**”h]”hŒeither”…””}”(hjWh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jUhjMubhŒ via ”…””}”(hjMh²hh³Nh´Nubj.)”}”(hŒ ``extack``”h]”hŒextack”…””}”(hjih²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjMubhŒ ”…””}”(hjMh²hh³Nh´NubjV)”}”(hŒ**or**”h]”hŒor”…””}”(hj{h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jUhjMubhŒO to system logs. Drivers should not try to report the same information to both.”…””}”(hjMh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÿh³hÇh´KŽhj h²hubeh}”(h]”Œerror-message-reporting”ah ]”h"]”Œerror message reporting”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K…ubeh}”(h]”Œsoftnet-driver-issues”ah ]”h"]”Œsoftnet driver issues”ah$]”h&]”uh1hÈhhh²hh³hÇh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hÍNŒ 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”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j jjjjjjƒj€jTjQj{jxjjj•j’jjŠj¼j¹jÿjüj˜j•uŒ nametypes”}”(j ‰j‰j‰jƒ‰jT‰j{‰j‰j•‰j‰j¼‰jÿ‰j˜‰uh}”(jhÊjhÝjhîj€jjQj0jxjWjj†j’j—jŠjöj¹j˜jüj¿j•j 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”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.