€•DŒ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 & bp->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_stop_queue(dev); 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 & bp->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_stop_queue(dev); 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²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“Kkubj)”}”(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“KmhjŠh²hubeh}”(h]”Œno-exclusive-ownership”ah ]”h"]”Œno exclusive ownership”ah$]”h&]”uh1hČhj†h²hh³hĒh“KkubhÉ)”}”(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“Kqubj)”}”(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“Kshj±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“Kwhj±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“Kqubeh}”(h]”Œtransmit-path-guidelines”ah ]”h"]”Œtransmit path guidelines”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”hnj _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”}”(jjžjjjjjƒj€jTjQj{jxjłjöj‡j„jj|j®j«jńjīuŒ nametypes”}”(j‰j‰j‰jƒ‰jT‰j{‰jł‰j‡‰j‰j®‰jń‰uh}”(jžhŹjhŻjhīj€jjQj0jxjWjö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.