git: 2409e2436a53 - main - net80211: add driver registration documentation

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Sun, 11 Oct 2026 22:29:40 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=2409e2436a5369146f4cc99463ce5314dba0b7d4

commit 2409e2436a5369146f4cc99463ce5314dba0b7d4
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2026-10-11 22:26:14 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
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.