2 * Copyright (c) 2020-2023 The FreeBSD Foundation
3 * Copyright (c) 2020-2021 Bjoern A. Zeeb
5 * This software was developed by Björn Zeeb under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Public functions are called linuxkpi_*().
32 * Internal (static) functions are called lkpi_*().
34 * The internal structures holding metadata over public structures are also
35 * called lkpi_xxx (usually with a member at the end called xxx).
36 * Note: we do not replicate the structure names but the general variable names
37 * for these (e.g., struct hw -> struct lkpi_hw, struct sta -> struct lkpi_sta).
38 * There are macros to access one from the other.
39 * We call the internal versions lxxx (e.g., hw -> lhw, sta -> lsta).
42 #ifndef _LKPI_SRC_LINUX_80211_H
43 #define _LKPI_SRC_LINUX_80211_H
45 /* #define LINUXKPI_DEBUG_80211 */
48 #define D80211_TODO 0x00000001
50 #ifndef D80211_IMPROVE
51 #define D80211_IMPROVE 0x00000002
53 #define D80211_IMPROVE_TXQ 0x00000004
54 #define D80211_TRACE 0x00000010
55 #define D80211_TRACEOK 0x00000020
56 #define D80211_TRACE_TX 0x00000100
57 #define D80211_TRACE_TX_DUMP 0x00000200
58 #define D80211_TRACE_RX 0x00001000
59 #define D80211_TRACE_RX_DUMP 0x00002000
60 #define D80211_TRACE_RX_BEACONS 0x00004000
61 #define D80211_TRACEX (D80211_TRACE_TX|D80211_TRACE_RX)
62 #define D80211_TRACEX_DUMP (D80211_TRACE_TX_DUMP|D80211_TRACE_RX_DUMP)
63 #define D80211_TRACE_STA 0x00010000
64 #define D80211_TRACE_MO 0x00100000
65 #define D80211_TRACE_MODE 0x0f000000
66 #define D80211_TRACE_MODE_HT 0x01000000
67 #define D80211_TRACE_MODE_VHT 0x02000000
68 #define D80211_TRACE_MODE_HE 0x04000000
69 #define D80211_TRACE_MODE_EHT 0x08000000
71 #define IMPROVE_TXQ(...) \
72 if (linuxkpi_debug_80211 & D80211_IMPROVE_TXQ) \
73 printf("%s:%d: XXX LKPI80211 IMPROVE_TXQ\n", __func__, __LINE__)
75 #define IMPROVE_HT(...) \
76 if (linuxkpi_debug_80211 & D80211_TRACE_MODE_HT) \
77 printf("%s:%d: XXX LKPI80211 IMPROVE_HT\n", __func__, __LINE__)
79 struct lkpi_radiotap_tx_hdr {
80 struct ieee80211_radiotap_header wt_ihdr;
83 uint16_t wt_chan_freq;
84 uint16_t wt_chan_flags;
86 #define LKPI_RTAP_TX_FLAGS_PRESENT \
87 ((1 << IEEE80211_RADIOTAP_FLAGS) | \
88 (1 << IEEE80211_RADIOTAP_RATE) | \
89 (1 << IEEE80211_RADIOTAP_CHANNEL))
91 struct lkpi_radiotap_rx_hdr {
92 struct ieee80211_radiotap_header wr_ihdr;
96 uint16_t wr_chan_freq;
97 uint16_t wr_chan_flags;
98 int8_t wr_dbm_antsignal;
99 int8_t wr_dbm_antnoise;
100 } __packed __aligned(8);
101 #define LKPI_RTAP_RX_FLAGS_PRESENT \
102 ((1 << IEEE80211_RADIOTAP_TSFT) | \
103 (1 << IEEE80211_RADIOTAP_FLAGS) | \
104 (1 << IEEE80211_RADIOTAP_RATE) | \
105 (1 << IEEE80211_RADIOTAP_CHANNEL) | \
106 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
107 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))
110 TAILQ_ENTRY(lkpi_txq) txq_entry;
115 uint32_t txq_generation;
116 struct sk_buff_head skbq;
119 struct ieee80211_txq txq __aligned(CACHE_LINE_SIZE);
121 #define TXQ_TO_LTXQ(_txq) container_of(_txq, struct lkpi_txq, txq)
125 TAILQ_ENTRY(lkpi_sta) lsta_entry;
126 struct ieee80211_node *ni;
128 /* Deferred TX path. */
129 /* Eventually we might want to migrate this into net80211 entirely. */
130 /* XXX-BZ can we use sta->txq[] instead directly? */
131 struct task txq_task;
135 struct ieee80211_key_conf *kc;
136 enum ieee80211_sta_state state;
137 bool added_to_drv; /* Driver knows; i.e. we called ...(). */
138 bool in_mgd; /* XXX-BZ should this be per-vif? */
141 struct ieee80211_sta sta __aligned(CACHE_LINE_SIZE);
143 #define STA_TO_LSTA(_sta) container_of(_sta, struct lkpi_sta, sta)
144 #define LSTA_TO_STA(_lsta) (&(_lsta)->sta)
147 TAILQ_ENTRY(lkpi_vif) lvif_entry;
148 struct ieee80211vap iv_vap;
151 struct wireless_dev wdev;
153 /* Other local stuff. */
154 int (*iv_newstate)(struct ieee80211vap *,
155 enum ieee80211_state, int);
156 struct ieee80211_node * (*iv_update_bss)(struct ieee80211vap *,
157 struct ieee80211_node *);
158 TAILQ_HEAD(, lkpi_sta) lsta_head;
159 struct lkpi_sta *lvif_bss;
160 bool lvif_bss_synched;
161 bool added_to_drv; /* Driver knows; i.e. we called add_interface(). */
163 bool hw_queue_stopped[IEEE80211_NUM_ACS];
166 struct ieee80211_vif vif __aligned(CACHE_LINE_SIZE);
168 #define VAP_TO_LVIF(_vap) container_of(_vap, struct lkpi_vif, iv_vap)
169 #define LVIF_TO_VAP(_lvif) (&(_lvif)->iv_vap)
170 #define VIF_TO_LVIF(_vif) container_of(_vif, struct lkpi_vif, vif)
171 #define LVIF_TO_VIF(_lvif) (&(_lvif)->vif)
174 struct lkpi_hw { /* name it mac80211_sc? */
175 const struct ieee80211_ops *ops;
176 struct ieee80211_scan_request *hw_req;
177 struct workqueue_struct *workq;
179 /* FreeBSD specific compat. */
180 /* Linux device is in hw.wiphy->dev after SET_IEEE80211_DEV(). */
181 struct ieee80211com *ic;
182 struct lkpi_radiotap_tx_hdr rtap_tx;
183 struct lkpi_radiotap_rx_hdr rtap_rx;
185 TAILQ_HEAD(, lkpi_vif) lvif_head;
191 uint32_t txq_generation[IEEE80211_NUM_ACS];
192 TAILQ_HEAD(, lkpi_txq) scheduled_txqs[IEEE80211_NUM_ACS];
194 /* Scan functions we overload to handle depending on scan mode. */
195 void (*ic_scan_curchan)(struct ieee80211_scan_state *,
197 void (*ic_scan_mindwell)(struct ieee80211_scan_state *);
199 /* Node functions we overload to sync state. */
200 struct ieee80211_node * (*ic_node_alloc)(struct ieee80211vap *,
201 const uint8_t [IEEE80211_ADDR_LEN]);
202 int (*ic_node_init)(struct ieee80211_node *);
203 void (*ic_node_cleanup)(struct ieee80211_node *);
204 void (*ic_node_free)(struct ieee80211_node *);
206 /* HT and later functions. */
207 int (*ic_recv_action)(struct ieee80211_node *,
208 const struct ieee80211_frame *,
209 const uint8_t *, const uint8_t *);
210 int (*ic_send_action)(struct ieee80211_node *,
212 int (*ic_ampdu_enable)(struct ieee80211_node *,
213 struct ieee80211_tx_ampdu *);
214 int (*ic_addba_request)(struct ieee80211_node *,
215 struct ieee80211_tx_ampdu *, int, int, int);
216 int (*ic_addba_response)(struct ieee80211_node *,
217 struct ieee80211_tx_ampdu *, int, int, int);
218 void (*ic_addba_stop)(struct ieee80211_node *,
219 struct ieee80211_tx_ampdu *);
220 void (*ic_addba_response_timeout)(struct ieee80211_node *,
221 struct ieee80211_tx_ampdu *);
222 void (*ic_bar_response)(struct ieee80211_node *,
223 struct ieee80211_tx_ampdu *, int);
224 int (*ic_ampdu_rx_start)(struct ieee80211_node *,
225 struct ieee80211_rx_ampdu *, int, int, int);
226 void (*ic_ampdu_rx_stop)(struct ieee80211_node *,
227 struct ieee80211_rx_ampdu *);
229 #define LKPI_MAC80211_DRV_STARTED 0x00000001
231 #define LKPI_LHW_SCAN_RUNNING 0x00000001
232 #define LKPI_LHW_SCAN_HW 0x00000002
236 int supbands; /* Number of supported bands. */
237 int max_rates; /* Maximum number of bitrates supported in any channel. */
238 int scan_ie_len; /* Length of common per-band scan IEs. */
244 struct ieee80211_hw hw __aligned(CACHE_LINE_SIZE);
246 #define LHW_TO_HW(_lhw) (&(_lhw)->hw)
247 #define HW_TO_LHW(_hw) container_of(_hw, struct lkpi_hw, hw)
249 struct lkpi_chanctx {
250 bool added_to_drv; /* Managed by MO */
251 struct ieee80211_chanctx_conf conf __aligned(CACHE_LINE_SIZE);
253 #define LCHANCTX_TO_CHANCTX_CONF(_lchanctx) \
255 #define CHANCTX_CONF_TO_LCHANCTX(_conf) \
256 container_of(_conf, struct lkpi_chanctx, conf)
259 const struct cfg80211_ops *ops;
262 struct wiphy wiphy __aligned(CACHE_LINE_SIZE);
264 #define WIPHY_TO_LWIPHY(_wiphy) container_of(_wiphy, struct lkpi_wiphy, wiphy)
265 #define LWIPHY_TO_WIPHY(_lwiphy) (&(_lwiphy)->wiphy)
267 #define LKPI_80211_LHW_LOCK_INIT(_lhw) \
268 sx_init_flags(&(_lhw)->sx, "lhw", SX_RECURSE);
269 #define LKPI_80211_LHW_LOCK_DESTROY(_lhw) \
270 sx_destroy(&(_lhw)->sx);
271 #define LKPI_80211_LHW_LOCK(_lhw) \
272 sx_xlock(&(_lhw)->sx)
273 #define LKPI_80211_LHW_UNLOCK(_lhw) \
274 sx_xunlock(&(_lhw)->sx)
275 #define LKPI_80211_LHW_LOCK_ASSERT(_lhw) \
276 sx_assert(&(_lhw)->sx, SA_LOCKED)
277 #define LKPI_80211_LHW_UNLOCK_ASSERT(_lhw) \
278 sx_assert(&(_lhw)->sx, SA_UNLOCKED)
280 #define LKPI_80211_LHW_SCAN_LOCK_INIT(_lhw) \
281 mtx_init(&(_lhw)->scan_mtx, "lhw-scan", NULL, MTX_DEF | MTX_RECURSE);
282 #define LKPI_80211_LHW_SCAN_LOCK_DESTROY(_lhw) \
283 mtx_destroy(&(_lhw)->scan_mtx);
284 #define LKPI_80211_LHW_SCAN_LOCK(_lhw) \
285 mtx_lock(&(_lhw)->scan_mtx)
286 #define LKPI_80211_LHW_SCAN_UNLOCK(_lhw) \
287 mtx_unlock(&(_lhw)->scan_mtx)
288 #define LKPI_80211_LHW_SCAN_LOCK_ASSERT(_lhw) \
289 mtx_assert(&(_lhw)->scan_mtx, MA_OWNED)
290 #define LKPI_80211_LHW_SCAN_UNLOCK_ASSERT(_lhw) \
291 mtx_assert(&(_lhw)->scan_mtx, MA_NOTOWNED)
293 #define LKPI_80211_LHW_TXQ_LOCK_INIT(_lhw) \
294 mtx_init(&(_lhw)->txq_mtx, "lhw-txq", NULL, MTX_DEF | MTX_RECURSE);
295 #define LKPI_80211_LHW_TXQ_LOCK_DESTROY(_lhw) \
296 mtx_destroy(&(_lhw)->txq_mtx);
297 #define LKPI_80211_LHW_TXQ_LOCK(_lhw) \
298 mtx_lock(&(_lhw)->txq_mtx)
299 #define LKPI_80211_LHW_TXQ_UNLOCK(_lhw) \
300 mtx_unlock(&(_lhw)->txq_mtx)
301 #define LKPI_80211_LHW_TXQ_LOCK_ASSERT(_lhw) \
302 mtx_assert(&(_lhw)->txq_mtx, MA_OWNED)
303 #define LKPI_80211_LHW_TXQ_UNLOCK_ASSERT(_lhw) \
304 mtx_assert(&(_lhw)->txq_mtx, MA_NOTOWNED)
306 #define LKPI_80211_LHW_LVIF_LOCK(_lhw) sx_xlock(&(_lhw)->lvif_sx)
307 #define LKPI_80211_LHW_LVIF_UNLOCK(_lhw) sx_xunlock(&(_lhw)->lvif_sx)
309 #define LKPI_80211_LVIF_LOCK(_lvif) mtx_lock(&(_lvif)->mtx)
310 #define LKPI_80211_LVIF_UNLOCK(_lvif) mtx_unlock(&(_lvif)->mtx)
312 #define LKPI_80211_LSTA_LOCK(_lsta) mtx_lock(&(_lsta)->txq_mtx)
313 #define LKPI_80211_LSTA_UNLOCK(_lsta) mtx_unlock(&(_lsta)->txq_mtx)
315 #define LKPI_80211_LTXQ_LOCK_INIT(_ltxq) \
316 mtx_init(&(_ltxq)->ltxq_mtx, "ltxq", NULL, MTX_DEF);
317 #define LKPI_80211_LTXQ_LOCK_DESTROY(_ltxq) \
318 mtx_destroy(&(_ltxq)->ltxq_mtx);
319 #define LKPI_80211_LTXQ_LOCK(_ltxq) \
320 mtx_lock(&(_ltxq)->ltxq_mtx)
321 #define LKPI_80211_LTXQ_UNLOCK(_ltxq) \
322 mtx_unlock(&(_ltxq)->ltxq_mtx)
323 #define LKPI_80211_LTXQ_LOCK_ASSERT(_ltxq) \
324 mtx_assert(&(_ltxq)->ltxq_mtx, MA_OWNED)
325 #define LKPI_80211_LTXQ_UNLOCK_ASSERT(_ltxq) \
326 mtx_assert(&(_ltxq)->ltxq_mtx, MA_NOTOWNED)
328 int lkpi_80211_mo_start(struct ieee80211_hw *);
329 void lkpi_80211_mo_stop(struct ieee80211_hw *);
330 int lkpi_80211_mo_get_antenna(struct ieee80211_hw *, u32 *, u32 *);
331 int lkpi_80211_mo_set_frag_threshold(struct ieee80211_hw *, uint32_t);
332 int lkpi_80211_mo_set_rts_threshold(struct ieee80211_hw *, uint32_t);
333 int lkpi_80211_mo_add_interface(struct ieee80211_hw *, struct ieee80211_vif *);
334 void lkpi_80211_mo_remove_interface(struct ieee80211_hw *, struct ieee80211_vif *);
335 int lkpi_80211_mo_hw_scan(struct ieee80211_hw *, struct ieee80211_vif *,
336 struct ieee80211_scan_request *);
337 void lkpi_80211_mo_cancel_hw_scan(struct ieee80211_hw *, struct ieee80211_vif *);
338 void lkpi_80211_mo_sw_scan_complete(struct ieee80211_hw *, struct ieee80211_vif *);
339 void lkpi_80211_mo_sw_scan_start(struct ieee80211_hw *, struct ieee80211_vif *,
341 u64 lkpi_80211_mo_prepare_multicast(struct ieee80211_hw *,
342 struct netdev_hw_addr_list *);
343 void lkpi_80211_mo_configure_filter(struct ieee80211_hw *, unsigned int,
344 unsigned int *, u64);
345 int lkpi_80211_mo_sta_state(struct ieee80211_hw *, struct ieee80211_vif *,
346 struct lkpi_sta *, enum ieee80211_sta_state);
347 int lkpi_80211_mo_config(struct ieee80211_hw *, uint32_t);
348 int lkpi_80211_mo_assign_vif_chanctx(struct ieee80211_hw *, struct ieee80211_vif *,
349 struct ieee80211_bss_conf *, struct ieee80211_chanctx_conf *);
350 void lkpi_80211_mo_unassign_vif_chanctx(struct ieee80211_hw *, struct ieee80211_vif *,
351 struct ieee80211_bss_conf *, struct ieee80211_chanctx_conf **);
352 int lkpi_80211_mo_add_chanctx(struct ieee80211_hw *, struct ieee80211_chanctx_conf *);
353 void lkpi_80211_mo_change_chanctx(struct ieee80211_hw *,
354 struct ieee80211_chanctx_conf *, uint32_t);
355 void lkpi_80211_mo_remove_chanctx(struct ieee80211_hw *,
356 struct ieee80211_chanctx_conf *);
357 void lkpi_80211_mo_bss_info_changed(struct ieee80211_hw *, struct ieee80211_vif *,
358 struct ieee80211_bss_conf *, uint64_t);
359 int lkpi_80211_mo_conf_tx(struct ieee80211_hw *, struct ieee80211_vif *,
360 uint32_t, uint16_t, const struct ieee80211_tx_queue_params *);
361 void lkpi_80211_mo_flush(struct ieee80211_hw *, struct ieee80211_vif *,
363 void lkpi_80211_mo_mgd_prepare_tx(struct ieee80211_hw *, struct ieee80211_vif *,
364 struct ieee80211_prep_tx_info *);
365 void lkpi_80211_mo_mgd_complete_tx(struct ieee80211_hw *, struct ieee80211_vif *,
366 struct ieee80211_prep_tx_info *);
367 void lkpi_80211_mo_tx(struct ieee80211_hw *, struct ieee80211_tx_control *,
369 void lkpi_80211_mo_wake_tx_queue(struct ieee80211_hw *, struct ieee80211_txq *);
370 void lkpi_80211_mo_sync_rx_queues(struct ieee80211_hw *);
371 void lkpi_80211_mo_sta_pre_rcu_remove(struct ieee80211_hw *,
372 struct ieee80211_vif *, struct ieee80211_sta *);
373 int lkpi_80211_mo_set_key(struct ieee80211_hw *, enum set_key_cmd,
374 struct ieee80211_vif *, struct ieee80211_sta *,
375 struct ieee80211_key_conf *);
376 int lkpi_80211_mo_ampdu_action(struct ieee80211_hw *, struct ieee80211_vif *,
377 struct ieee80211_ampdu_params *);
380 #endif /* _LKPI_SRC_LINUX_80211_H */