From nobody Sun Oct 11 22:29:40 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4j2wJN5rFDz6w8PB for ; Sun, 11 Oct 2026 22:29:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4j2wJN4P4wz59VR for ; Sun, 11 Oct 2026 22:29:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791757780; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NJy7vuBulTxG/ozzmiiP5J1MD1Mfs9avwwg33Yl3kiM=; b=tm4ZCeWajPnpisGn5z9Tua51shf83XYey27AEIdhUeWsFQkLUwb0CKFMEoLBfn0+ica6fF vp+Gowlx5lHFojoCARsGjzUjCAgnBvLXVA2gJt2mkIZKTYB2CJYI9aVnB0Xm081URj7PpL P3iXOZ0zdreLjhgl2trM8Pmch8z5Oydz0J3qBr87v5Nu7ZLF5u9/5sPaGnN/snxpr6zc7D bQPNaxCC/rIQ3J6z2cU2G97eB4a4d2SJePGtueebtVTI8yBrvJhD7wG8pCswe4hvPeSInJ GAKY9iETj+Odf8lgclylU7ljOFOVcpjZ9unA50LqcCjvy8O1AyLqkFCxNA3MLQ== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1791757780; b=YWKq8hqItAt1LP+a07BDf5baGkFvE1qbuiQer8AFQ0kZhYimLw7aiONDn5oaYlbtMU2QXZ nuWZYUIe6dO6UT3Ggh3p7qSHbjGh2uj2kD5RDerO9hZvXQFVxkO8l2rfQqdhtu/M+oKEwc ZNT84S36oEj0q49BhYS5va3kS39lJVV/S6AzNOn8yQYiaKd3O/9NQLCFsAgBS17YXGHWsX 6wMfhAMPgfeKOZBPVmeGhQ/0SJGnhOrnLNOiItzYK79gwphx6iBaI9r6AF0QE9lcWLbQsB rf+a/bYM/bQabmGkNDwt1KDnw1u6SWS/HmDlgoXK/hxW9FS4EWLeLHT5HTttHA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791757780; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NJy7vuBulTxG/ozzmiiP5J1MD1Mfs9avwwg33Yl3kiM=; b=pubmkwgZg89yMN8LlKzB00Rqmwa0icnlsl2XCQWbOm6unW/KeH+Um19MrzcOBpF0hxNXeF By1KC12imZ+cKXkzfl4bh5EZ4jZdWu7b6ASWo0NubgGwyy9mMmore06dwquiYGF/vfxn72 TWDZFQWxocszezJzGUQUYDks9iV+HhoiZy/1zroSFPgC7wgdB4EO9hBmyeXpfPgbnL0Qmw jUXxZewO75wMW9efFELqho2xLpHWus2HzhUI4uitP9JHvM+QPA2oR+7phn+r4TDJVrT/6w lqYfpZ/PFSwNzJLI/DLx3Y4L9tZsEOwMlm0WSNN8eI0P52vpd9WMvuC0IEqaXA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4j2wJN3Svdz11K9 for ; Sun, 11 Oct 2026 22:29:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1dd93 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 11 Oct 2026 22:29:40 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Adrian Chadd Subject: git: 2409e2436a53 - main - net80211: add driver registration documentation List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: Commit messages for the main branch of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: adrian X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 2409e2436a5369146f4cc99463ce5314dba0b7d4 Auto-Submitted: auto-generated Date: Sun, 11 Oct 2026 22:29:40 +0000 Message-Id: <6acc0dd4.1dd93.199d9b32@gitrepo.freebsd.org> The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=2409e2436a5369146f4cc99463ce5314dba0b7d4 commit 2409e2436a5369146f4cc99463ce5314dba0b7d4 Author: Adrian Chadd AuthorDate: 2026-10-11 22:26:14 +0000 Commit: Adrian Chadd CommitDate: 2026-10-11 22:29:33 +0000 net80211: add driver registration documentation This is a brief introduction into the top-level newbus driver methods and net80211 driver registration. Differential Revision: https://reviews.freebsd.org/D60503 Reviewed by: ziaee, zi --- sys/net80211/DRIVER_REGISTRATION.md | 252 ++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) diff --git a/sys/net80211/DRIVER_REGISTRATION.md b/sys/net80211/DRIVER_REGISTRATION.md new file mode 100644 index 000000000000..087665b7af56 --- /dev/null +++ b/sys/net80211/DRIVER_REGISTRATION.md @@ -0,0 +1,252 @@ +# Registering a net80211 driver + +This document covers the top level driver registration and +'struct ieee80211com' which represents a net80211 device +to the rest of the kernel. + +## Overview + +Each net80211 driver needs to register with net80211. Drivers +typically do this by putting 'struct ieee80211com' at the +top of their driver softc structure and defining a macro +that lets the driver author convert between the driver softc +struct and the ieee80211com struct. + +There currently isn't a call to allocate or initialise +a net80211com structure. + +Drivers will go through and initialise fields in the ieee80211com +struct which describes the hardware capabilities, crypto +support, operating characteristics in various modes (11abg, +11n, 11ac), configure the list of available / supported +channels, and then finally call ieee80211_ifattach(). + +There is a specific order with which to do the initialisation, +as various parts of the net80211 setup process will set +defaults which can then be overridden by the driver. + +## Top level driver behaviour + +There are a few top level driver methods that need implementing +by all FreeBSD drivers. They are, in order here: + + * probe() + * attach() + * detach() + * suspend() + * resume() + * shutdown() + +### Driver Probe + +There is typically nothing 802.11 specific about the driver +probe phase. This is normally just matching on the bus +and device information and stating whether this driver +supports the given hardware. + +### Driver Attach + +The attach path involves listing out the NIC hardware, firmware +and feature support, initialising net80211, overriding its +defaults and then completing the net80211 registration process. + +Drivers will typically do as much work up front as needed to +ensure the device is available and gather configuration before +the net80211 registration process can take place. This includes +information such as the available channels, NIC operating modes +and MAC address. Devices which require firmware may need to +initialise the hardware and load the firmware in order to +fetch this configuration which may require interrupts to be +available. + +The order of operations is typically: + +* Do the device specific initialisation - busdma, memory, + interrupt allocation, check firmware, etc - so it can fail + before net80211 registration happens. + +* Initialise the ieee80211com struct with a few things: + + + ic->ic_softc - point to the driver softc. + + ic->ic_name - the driver name, typically device_get_nameunit(dev). + + ic->ic_phytype = just set this to IEEE80211_T_OFDM for now, + its no longer needed. + + ic->ic_opmode = IEEE80211_M_STA - default to STA mode, but again + its not needed these days. + + ic->ic_caps - device capabilities (STA, AP, MONITOR, WPA/WPA2, etc.). + + ic->ic_flags_ext - extended capabilities/flags (HT, VHT, etc.). + + 802.11n and later NICs need to set ic->ic_rxstream and ic->ic_txstream + to indicate the number of TX/RX spatial streams (not antennas, + that is NOT 1:1 spatial streams). + + 802.11n and later devices need to initialise ic->ic_htcaps with + the HT capabilities. + + 802.11ac devices need to also initialise ic->ic_vht_cap with + the VHT capabilities. + +* The driver next needs to initialise the set of supported channels. + This typically involves calls to ieee80211_add_channels_default_2ghz() + and ieee80211_add_channel_list_5ghz(). + +* The driver then calls ieee80211_ifattach() to initialise the + net80211 state for this driver and set the driver defaults. + +* Next, the driver will initialise the 'struct ieee80211com' level + function methods, most of which are covered later in this document. + +* Next, if supported, the driver will attach radiotap state + via a call to ieee80211_radiotap_attach(). + +* Next, the driver can override the default set of software and hardware + supported ciphers via calls to ieee80211_set_hardware_ciphers() + and ieee80211_set_software_ciphers(). + +* Finally, if required, the driver can call ieee80211_announce() to + verbosely announce the net80211 attach state. + +### Driver Detach + +The detach pass requires some care. It's done as part of newbus rather +than net80211. + +This typically involves a few steps: + + * First, the driver needs to stop any of its current work. + For most drivers this will involve setting some state to inform + the rest of the driver it is shutting down, then shutting down the chipset + activity, DMA and firmware interfaces so the hardware is quiet. + + * Next the driver will stop its own activity - callouts, taskqueues, etc. + + * The driver will then wait to make sure activity has stopped. + + * Next the driver will shut off the hardware as appropriate. + + * The driver will then call ieee80211_ifdetach() to detach the net80211 + state and shut down any left over resources. Note that this will + loop through and destroy virtual interfaces and other state - so those + paths need to know that the driver is shutting down, rather than just + deleting the virtual interfaces. + + * Finally the driver will release its hardware, driver, kernel, etc + resources and return. + +The driver author must assume that a detach/shutdown call means the +hardware is no longer available. + +### Driver Suspend + +The suspend driver call happens from newbus, not from net80211. + +The driver is required to call ieee80211_suspend_all() to suspend +all activity on the virtual interfaces and then do any work it +needs to do in order to suspend the hardware. + +Note that ieee80211_suspend_all() will go through the normal +virtual interface transition to idle, and then will call the ic->ic_parent() +method to eventually shut down the parent interface. + +### Driver Resume + +The resume driver call happens from newbus, not from net80211. + +The driver is required to do any required work to bring the hardware +back from suspend, and then call call ieee80211_resume_all() to +resume the virtual interfaces. + +Note that ieee80211_resume_all() will go through the normal +virtual interface transition to active, and will call the ic->ic_parent() +method to notify the driver that one or more virtual interfaces +is starting. The driver will need to do the relevant work to +re-initialise the hardware and firmware state. + +### Driver Shutdown + +The shutdown driver call happens from newbus, not from net80211. + +This is invocated when the hardware is shutting down. Typically +this will be a much shorter version of the detach method where +the driver and hardware are stopped, but resources do not need +to be cleaned up. + +The driver author must assume that a detach/shutdown call means the +hardware is no longer available. + +## Top level control methods + +There are a few top level functions that need to be implemented +for general net80211 driver work to happen. This is not currently +a comprehensive list; see the 'struct ieee80211com' list and other +documentation sections to further understand what drivers need +to implement. + + * ic_parent() - called to notify the driver that the parent + interface needs starting or stopping. This will be called + when at least one VAP is active, or all VAPs are inactive. + * ic_ioctl() - the ioctl() interface to the driver; this is accessible + via ioctl() calls on a socket with a reference to the VAP. + * ic_vap_create() / ic_vap_delete() - create and delete VAPs. + * ic_getradiocaps() - get the radio capabilities and channel list. + * ic_setregdomain() - get/set the regulatory domain state/configuration. + * ic_set_quiet() - set the quiet time IE configuration. + * ic_transmit(), ic_send_mgmt(), ic_raw_xmit() - the transmit path. + * ic_update_slot() - NIC level slot timing update (for 11b/11g). + * ic_update_mcast() - update NIC level multicast state changes. + * ic_update_promisc() - update NIC level promiscuous settings. + * ic_newassoc() - station association / update. + * ic_tdma_tdma_update() - TDMA configuration for ath(4) NICs. + * ic_node_alloc() / ic_node_free() / ic_node_init() / ic_node_cleanup() - + 'struct ieee80211_node' node allocation, free and management. + * ic_node_age() / ic_node_drain() - handle node aging and timeout. + * ic_node_getrssi() /ic_node_getsignal() / ic_node_getmimoinfo() - + get node signal strength and noise floor information. + * ic_scan_start() / ic_scan_end() / ic_scan_curchan() / ic_scan_mindwell() - + configure and manage scanning. + * ic_set_channel() - set the channel (for NICs that need it + handled by net80211 rather than by firmware, etc.) + * ic_recv_action() / ic_send_action() - 802.11 action frame send/receive + override methods. + +There are also quite a few methods controlling 802.11n ADDBA, AMPDU, BAR, +channel width and other processing. These only need to be implemented +for 802.11n and later devices. + +## Concurrency Notes + +The top level driver methods (besides probe and attach, of course) +may and are called during existing and overlapping operations. +Although newbus will not call e.g., suspend and resume together, +newbus may call detach (e.g., due to a hotplug detach event for USB) +whilst the driver is actively doing USB transfers. + +It is thus up to the driver to ensure that suitable ordering / locking +is performed between other driver entry points (transmit, receive, +ioctl handling, callouts/taskqueues, etc.) and the newbus driver +methods mentioned here (suspend, resume, shutdown, detach). + +The detach/shutdown methods are notably difficult to get right. +The detach method may be called during active work - VAP state +changes, ioctls, transmit/receive data, callouts/tasks - and +as it is not an asynchronous method, it needs to block until its +done, it needs to make sure existing work is completed AND +no new work is scheduled. + +## Future work + + * There is currently no methods to initialise 'struct ieee80211com' before + the driver does its work. It is just assumed to be zero-filled during + allocation. It would be nice to have a function that drivers call + to explicitly initialise it to some set of defaults, even if those + defaults are currently zero'ed memory. + + * The device is available once net80211_ifattach() is called. There likely + needs to be a method to mark the driver as actually ready once all of + the function pointers and state are completely initialised. + + * Similarly to shutdown, it may be nice to provide a net80211 method to + tell net80211 the whole device is going down, so stop trying to schedule + further work (drop packets, don't call timers, ioctls will fail, etc.) + + * There are almost no default methods for the above function pointers - + net80211 will just panic if they aren't provided. It may be nice + to provide default methods so a very simple driver can probe/attach + fail VAP creation without panicing, do suspend, resume and detach/shutdown.