aboutsummaryrefslogtreecommitdiff
path: root/sys/net80211/DRIVER_REGISTRATION.md
blob: 087665b7af56078acaa5f152b1642c8fb2d10677 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
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.