€•CŒ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Œ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()”…””}”(hhíhž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”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hj hžhhŸh³h Kubhµ)”}”(hhh]”(hº)”}”(hŒ Quiescence”h]”hŒ Quiescence”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjhžhhŸh³h Kubhì)”}”(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.”…””}”(hj-hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëhŸh³h Khjhžhubeh}”(h]”Œ quiescence”ah ]”h"]”Œ quiescence”ah$]”h&]”uh1h´hj hžhhŸh³h Kubhµ)”}”(hhh]”(hº)”}”(hŒ Auto-close”h]”hŒ Auto-close”…””}”(hjFhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjChžhhŸh³h Kubhì)”}”(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.”…””}”(hjThžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëhŸh³h KhjChžhubeh}”(h]”Œ auto-close”ah ]”h"]”Œ auto-close”ah$]”h&]”uh1h´hj hž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”…””}”(hjuhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjrhž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&ubhì)”}”(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žhubhì)”}”(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žhubhì)”}”(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 Keubhì)”}”(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.”…””}”(hjóhž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žhubhì)”}”(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žhubhì)”}”(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 ”…””}”(hjhžhhŸNh NubhŒliteral”“”)”}”(hŒ``stop``”h]”hŒstop”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubhŒ‘ 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.”…””}”(hjhž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žhubhì)”}”(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 ”…””}”(hj4hžhhŸNh NubhŒemphasis”“”)”}”(hŒ*not*”h]”hŒnot”…””}”(hj>hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j<hj4ubhŒt prevent false wake ups when the ring is full! Drivers should check for ring full at the start for the xmit handler.”…””}”(hj4hž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 Khjâhžhubhì)”}”(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.”…””}”(hjWhž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´hjrhžhhŸh³h K&ubhµ)”}”(hhh]”(hº)”}”(hŒNo exclusive ownership”h]”hŒNo exclusive ownership”…””}”(hjyhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjvhžhhŸh³h Kkubhì)”}”(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 Kmhjvhžhubeh}”(h]”Œno-exclusive-ownership”ah ]”h"]”Œno exclusive ownership”ah$]”h&]”uh1h´hjrhžhhŸh³h Kkubhµ)”}”(hhh]”(hº)”}”(hŒTimely completions”h]”hŒTimely completions”…””}”(hj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjhžhhŸh³h Kqubhì)”}”(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 Kshjhžhubhì)”}”(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 Kwhjhžhubhì)”}”(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}hjhžhubeh}”(h]”Œtimely-completions”ah ]”h"]”Œtimely completions”ah$]”h&]”uh1h´hjrhž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”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íjêjjjhýjojlj@j=jgjdjåjâjsjpjkjhjšj—jÝjÚuŒ nametypes”}”(jí‰j‰j‰jo‰j@‰jg‰jå‰js‰jk‰jš‰j݉uh}”(jêh¶jhÉhýhÚjlj j=jjdjCjâjrjpjƒjhjâj—jvjÚjuŒ 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.