#ifndef _LKPI_SRC_LINUX_80211_H
#define _LKPI_SRC_LINUX_80211_H
#include "opt_wlan.h"
#if defined(IEEE80211_DEBUG) && !defined(LINUXKPI_DEBUG_80211)
#define LINUXKPI_DEBUG_80211
#endif
#ifndef D80211_TODO
#define D80211_TODO 0x00000001
#endif
#ifndef D80211_IMPROVE
#define D80211_IMPROVE 0x00000002
#endif
#define D80211_IMPROVE_TXQ 0x00000004
#define D80211_TRACE 0x00000010
#define D80211_TRACEOK 0x00000020
#define D80211_SCAN 0x00000040
#define D80211_SCAN_BEACON 0x00000080
#define D80211_TRACE_TX 0x00000100
#define D80211_TRACE_TX_DUMP 0x00000200
#define D80211_TRACE_RX 0x00001000
#define D80211_TRACE_RX_DUMP 0x00002000
#define D80211_TRACE_RX_BEACONS 0x00004000
#define D80211_TRACEX (D80211_TRACE_TX|D80211_TRACE_RX)
#define D80211_TRACEX_DUMP (D80211_TRACE_TX_DUMP|D80211_TRACE_RX_DUMP)
#define D80211_TRACE_STA 0x00010000
#define D80211_TRACE_HW_CRYPTO 0x00020000
#define D80211_TRACE_MO 0x00100000
#define D80211_TRACE_MODE 0x0f000000
#define D80211_TRACE_MODE_HT 0x01000000
#define D80211_TRACE_MODE_VHT 0x02000000
#define D80211_TRACE_MODE_HE 0x04000000
#define D80211_TRACE_MODE_EHT 0x08000000
#ifdef LINUXKPI_DEBUG_80211
#define TRACE_SCAN(ic, fmt, ...) \
if (linuxkpi_debug_80211 & D80211_SCAN) \
printf("%s:%d: %s SCAN " fmt "\n", \
__func__, __LINE__, ic->ic_name, ##__VA_ARGS__)
#define TRACE_SCAN_BEACON(ic, fmt, ...) \
if (linuxkpi_debug_80211 & D80211_SCAN_BEACON) \
printf("%s:%d: %s SCAN " fmt "\n", \
__func__, __LINE__, ic->ic_name, ##__VA_ARGS__)
#else
#define TRACE_SCAN(...) do {} while (0)
#define TRACE_SCAN_BEACON(...) do {} while (0)
#endif
#define IMPROVE_TXQ(...) \
if (linuxkpi_debug_80211 & D80211_IMPROVE_TXQ) \
printf("%s:%d: XXX LKPI80211 IMPROVE_TXQ\n", __func__, __LINE__)
#define IMPROVE_HT(fmt, ...) \
if (linuxkpi_debug_80211 & D80211_TRACE_MODE_HT) \
printf("%s:%d: XXX LKPI80211 IMPROVE_HT " fmt "\n", \
__func__, __LINE__, ##__VA_ARGS__);
#define MTAG_ABI_LKPI80211 1707696513
#ifdef LKPI_80211_USE_MTAG
#define LKPI80211_TAG_RXNI 0
struct lkpi_80211_tag_rxni {
struct ieee80211_node *ni;
};
#endif
struct lkpi_radiotap_tx_hdr {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
} __packed;
#define LKPI_RTAP_TX_FLAGS_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL))
struct lkpi_radiotap_rx_hdr {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsft;
uint8_t wr_flags;
uint8_t wr_rate;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_dbm_antsignal;
int8_t wr_dbm_antnoise;
} __packed __aligned(8);
#define LKPI_RTAP_RX_FLAGS_PRESENT \
((1 << IEEE80211_RADIOTAP_TSFT) | \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))
struct lkpi_hw;
struct lkpi_txq {
TAILQ_ENTRY(lkpi_txq) txq_entry;
struct mtx ltxq_mtx;
bool seen_dequeue;
bool stopped;
uint32_t txq_generation;
struct sk_buff_head skbq;
uint64_t frms_enqueued;
uint64_t frms_dequeued;
uint64_t frms_tx;
struct ieee80211_txq txq __aligned(CACHE_LINE_SIZE);
};
#define TXQ_TO_LTXQ(_txq) container_of(_txq, struct lkpi_txq, txq)
struct lkpi_sta {
struct list_head lsta_list;
struct ieee80211_node *ni;
struct ieee80211_hw *hw;
struct task txq_task;
struct mbufq txq;
struct mtx txq_mtx;
struct ieee80211_key_conf *kc[IEEE80211_WEP_NKID];
enum ieee80211_sta_state state;
bool txq_ready;
bool added_to_drv;
bool in_mgd;
struct station_info sinfo;
uint64_t frms_tx;
struct ieee80211_sta sta __aligned(CACHE_LINE_SIZE);
};
#define STA_TO_LSTA(_sta) container_of(_sta, struct lkpi_sta, sta)
#define LSTA_TO_STA(_lsta) (&(_lsta)->sta)
struct lkpi_vif {
TAILQ_ENTRY(lkpi_vif) lvif_entry;
struct ieee80211vap iv_vap;
eventhandler_tag lvif_ifllevent;
struct sysctl_ctx_list sysctl_ctx;
struct mtx mtx;
struct wireless_dev wdev;
int (*iv_newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
struct ieee80211_node * (*iv_update_bss)(struct ieee80211vap *,
struct ieee80211_node *);
void (*iv_recv_mgmt)(struct ieee80211_node *,
struct mbuf *, int,
const struct ieee80211_rx_stats *,
int, int);
struct task sw_scan_task;
struct list_head lsta_list;
struct lkpi_sta *lvif_bss;
struct ieee80211_node *key_update_iv_bss;
int ic_unlocked;
int nt_unlocked;
int beacons;
bool lvif_bss_synched;
bool added_to_drv;
bool hw_queue_stopped[IEEE80211_NUM_ACS];
struct ieee80211_vif vif __aligned(CACHE_LINE_SIZE);
};
#define VAP_TO_LVIF(_vap) container_of(_vap, struct lkpi_vif, iv_vap)
#define LVIF_TO_VAP(_lvif) (&(_lvif)->iv_vap)
#define VIF_TO_LVIF(_vif) container_of(_vif, struct lkpi_vif, vif)
#define LVIF_TO_VIF(_lvif) (&(_lvif)->vif)
struct lkpi_hw {
const struct ieee80211_ops *ops;
struct ieee80211_scan_request *hw_req;
struct workqueue_struct *workq;
struct ieee80211com *ic;
struct lkpi_radiotap_tx_hdr rtap_tx;
struct lkpi_radiotap_rx_hdr rtap_rx;
TAILQ_HEAD(, lkpi_vif) lvif_head;
struct sx lvif_sx;
struct list_head lchanctx_list;
struct netdev_hw_addr_list mc_list;
unsigned int mc_flags;
struct sx mc_sx;
struct mtx txq_mtx;
uint32_t txq_generation[IEEE80211_NUM_ACS];
spinlock_t txq_scheduled_lock[IEEE80211_NUM_ACS];
TAILQ_HEAD(, lkpi_txq) txq_scheduled[IEEE80211_NUM_ACS];
spinlock_t txq_lock;
struct task rxq_task;
struct mbufq rxq;
struct mtx rxq_mtx;
void (*ic_scan_curchan)(struct ieee80211_scan_state *,
unsigned long);
void (*ic_scan_mindwell)(struct ieee80211_scan_state *);
struct ieee80211_node * (*ic_node_alloc)(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN]);
int (*ic_node_init)(struct ieee80211_node *);
void (*ic_node_cleanup)(struct ieee80211_node *);
void (*ic_node_free)(struct ieee80211_node *);
int (*ic_recv_action)(struct ieee80211_node *,
const struct ieee80211_frame *,
const uint8_t *, const uint8_t *);
int (*ic_send_action)(struct ieee80211_node *,
int, int, void *);
int (*ic_ampdu_enable)(struct ieee80211_node *,
struct ieee80211_tx_ampdu *);
int (*ic_addba_request)(struct ieee80211_node *,
struct ieee80211_tx_ampdu *, int, int, int);
int (*ic_addba_response)(struct ieee80211_node *,
struct ieee80211_tx_ampdu *, int, int, int);
void (*ic_addba_stop)(struct ieee80211_node *,
struct ieee80211_tx_ampdu *);
void (*ic_addba_response_timeout)(struct ieee80211_node *,
struct ieee80211_tx_ampdu *);
void (*ic_bar_response)(struct ieee80211_node *,
struct ieee80211_tx_ampdu *, int);
int (*ic_ampdu_rx_start)(struct ieee80211_node *,
struct ieee80211_rx_ampdu *, int, int, int);
void (*ic_ampdu_rx_stop)(struct ieee80211_node *,
struct ieee80211_rx_ampdu *);
#define LKPI_MAC80211_DRV_STARTED 0x00000001
uint32_t sc_flags;
#define LKPI_LHW_SCAN_RUNNING 0x00000001
#define LKPI_LHW_SCAN_HW 0x00000002
uint32_t scan_flags;
struct mtx scan_mtx;
int supbands;
int max_rates;
int scan_ie_len;
bool mc_all_multi;
bool update_wme;
bool rxq_stopped;
struct ieee80211_hw hw __aligned(CACHE_LINE_SIZE);
};
#define LHW_TO_HW(_lhw) (&(_lhw)->hw)
#define HW_TO_LHW(_hw) container_of(_hw, struct lkpi_hw, hw)
#define LKPI_LHW_SCAN_BITS \
"\010\1RUNING\2HW"
struct lkpi_chanctx {
struct list_head entry;
bool added_to_drv;
struct ieee80211_chanctx_conf chanctx_conf __aligned(CACHE_LINE_SIZE);
};
#define LCHANCTX_TO_CHANCTX_CONF(_lchanctx) \
(&(_lchanctx)->chanctx_conf)
#define CHANCTX_CONF_TO_LCHANCTX(_conf) \
container_of(_conf, struct lkpi_chanctx, chanctx_conf)
struct lkpi_wiphy {
const struct cfg80211_ops *ops;
struct work_struct wwk;
struct list_head wwk_list;
struct mtx wwk_mtx;
struct wiphy wiphy __aligned(CACHE_LINE_SIZE);
};
#define WIPHY_TO_LWIPHY(_wiphy) container_of(_wiphy, struct lkpi_wiphy, wiphy)
#define LWIPHY_TO_WIPHY(_lwiphy) (&(_lwiphy)->wiphy)
#define LKPI_80211_LWIPHY_WORK_LOCK_INIT(_lwiphy) \
mtx_init(&(_lwiphy)->wwk_mtx, "lwiphy-work", NULL, MTX_DEF);
#define LKPI_80211_LWIPHY_WORK_LOCK_DESTROY(_lwiphy) \
mtx_destroy(&(_lwiphy)->wwk_mtx)
#define LKPI_80211_LWIPHY_WORK_LOCK(_lwiphy) \
mtx_lock(&(_lwiphy)->wwk_mtx)
#define LKPI_80211_LWIPHY_WORK_UNLOCK(_lwiphy) \
mtx_unlock(&(_lwiphy)->wwk_mtx)
#define LKPI_80211_LWIPHY_WORK_LOCK_ASSERT(_lwiphy) \
mtx_assert(&(_lwiphy)->wwk_mtx, MA_OWNED)
#define LKPI_80211_LWIPHY_WORK_UNLOCK_ASSERT(_lwiphy) \
mtx_assert(&(_lwiphy)->wwk_mtx, MA_NOTOWNED)
#define LKPI_80211_LHW_SCAN_LOCK_INIT(_lhw) \
mtx_init(&(_lhw)->scan_mtx, "lhw-scan", NULL, MTX_DEF | MTX_RECURSE);
#define LKPI_80211_LHW_SCAN_LOCK_DESTROY(_lhw) \
mtx_destroy(&(_lhw)->scan_mtx);
#define LKPI_80211_LHW_SCAN_LOCK(_lhw) \
mtx_lock(&(_lhw)->scan_mtx)
#define LKPI_80211_LHW_SCAN_UNLOCK(_lhw) \
mtx_unlock(&(_lhw)->scan_mtx)
#define LKPI_80211_LHW_SCAN_LOCK_ASSERT(_lhw) \
mtx_assert(&(_lhw)->scan_mtx, MA_OWNED)
#define LKPI_80211_LHW_SCAN_UNLOCK_ASSERT(_lhw) \
mtx_assert(&(_lhw)->scan_mtx, MA_NOTOWNED)
#define LKPI_80211_LHW_TXQ_LOCK_INIT(_lhw) \
mtx_init(&(_lhw)->txq_mtx, "lhw-txq", NULL, MTX_DEF | MTX_RECURSE);
#define LKPI_80211_LHW_TXQ_LOCK_DESTROY(_lhw) \
mtx_destroy(&(_lhw)->txq_mtx);
#define LKPI_80211_LHW_TXQ_LOCK(_lhw) \
mtx_lock(&(_lhw)->txq_mtx)
#define LKPI_80211_LHW_TXQ_UNLOCK(_lhw) \
mtx_unlock(&(_lhw)->txq_mtx)
#define LKPI_80211_LHW_TXQ_LOCK_ASSERT(_lhw) \
mtx_assert(&(_lhw)->txq_mtx, MA_OWNED)
#define LKPI_80211_LHW_TXQ_UNLOCK_ASSERT(_lhw) \
mtx_assert(&(_lhw)->txq_mtx, MA_NOTOWNED)
#define LKPI_80211_LHW_RXQ_LOCK_INIT(_lhw) \
mtx_init(&(_lhw)->rxq_mtx, "lhw-rxq", NULL, MTX_DEF | MTX_RECURSE);
#define LKPI_80211_LHW_RXQ_LOCK_DESTROY(_lhw) \
mtx_destroy(&(_lhw)->rxq_mtx);
#define LKPI_80211_LHW_RXQ_LOCK(_lhw) \
mtx_lock(&(_lhw)->rxq_mtx)
#define LKPI_80211_LHW_RXQ_UNLOCK(_lhw) \
mtx_unlock(&(_lhw)->rxq_mtx)
#define LKPI_80211_LHW_RXQ_LOCK_ASSERT(_lhw) \
mtx_assert(&(_lhw)->rxq_mtx, MA_OWNED)
#define LKPI_80211_LHW_RXQ_UNLOCK_ASSERT(_lhw) \
mtx_assert(&(_lhw)->rxq_mtx, MA_NOTOWNED)
#define LKPI_80211_LHW_LVIF_LOCK(_lhw) sx_xlock(&(_lhw)->lvif_sx)
#define LKPI_80211_LHW_LVIF_UNLOCK(_lhw) sx_xunlock(&(_lhw)->lvif_sx)
#define LKPI_80211_LHW_MC_LOCK_INIT(_lhw) \
sx_init_flags(&lhw->mc_sx, "lhw-mc", 0);
#define LKPI_80211_LHW_MC_LOCK_DESTROY(_lhw) \
sx_destroy(&lhw->mc_sx);
#define LKPI_80211_LHW_MC_LOCK(_lhw) sx_xlock(&(_lhw)->mc_sx)
#define LKPI_80211_LHW_MC_UNLOCK(_lhw) sx_xunlock(&(_lhw)->mc_sx)
#define LKPI_80211_LVIF_LOCK(_lvif) mtx_lock(&(_lvif)->mtx)
#define LKPI_80211_LVIF_UNLOCK(_lvif) mtx_unlock(&(_lvif)->mtx)
#define LKPI_80211_LSTA_TXQ_LOCK_INIT(_lsta) \
mtx_init(&(_lsta)->txq_mtx, "lsta-txq", NULL, MTX_DEF);
#define LKPI_80211_LSTA_TXQ_LOCK_DESTROY(_lsta) \
mtx_destroy(&(_lsta)->txq_mtx);
#define LKPI_80211_LSTA_TXQ_LOCK(_lsta) \
mtx_lock(&(_lsta)->txq_mtx)
#define LKPI_80211_LSTA_TXQ_UNLOCK(_lsta) \
mtx_unlock(&(_lsta)->txq_mtx)
#define LKPI_80211_LSTA_TXQ_LOCK_ASSERT(_lsta) \
mtx_assert(&(_lsta)->txq_mtx, MA_OWNED)
#define LKPI_80211_LSTA_TXQ_UNLOCK_ASSERT(_lsta) \
mtx_assert(&(_lsta)->txq_mtx, MA_NOTOWNED)
#define LKPI_80211_LTXQ_LOCK_INIT(_ltxq) \
mtx_init(&(_ltxq)->ltxq_mtx, "ltxq", NULL, MTX_DEF);
#define LKPI_80211_LTXQ_LOCK_DESTROY(_ltxq) \
mtx_destroy(&(_ltxq)->ltxq_mtx);
#define LKPI_80211_LTXQ_LOCK(_ltxq) \
mtx_lock(&(_ltxq)->ltxq_mtx)
#define LKPI_80211_LTXQ_UNLOCK(_ltxq) \
mtx_unlock(&(_ltxq)->ltxq_mtx)
#define LKPI_80211_LTXQ_LOCK_ASSERT(_ltxq) \
mtx_assert(&(_ltxq)->ltxq_mtx, MA_OWNED)
#define LKPI_80211_LTXQ_UNLOCK_ASSERT(_ltxq) \
mtx_assert(&(_ltxq)->ltxq_mtx, MA_NOTOWNED)
int lkpi_80211_mo_start(struct ieee80211_hw *);
void lkpi_80211_mo_stop(struct ieee80211_hw *, bool);
int lkpi_80211_mo_get_antenna(struct ieee80211_hw *, u32 *, u32 *);
int lkpi_80211_mo_set_frag_threshold(struct ieee80211_hw *, uint32_t);
int lkpi_80211_mo_set_rts_threshold(struct ieee80211_hw *, uint32_t);
int lkpi_80211_mo_add_interface(struct ieee80211_hw *, struct ieee80211_vif *);
void lkpi_80211_mo_remove_interface(struct ieee80211_hw *, struct ieee80211_vif *);
int lkpi_80211_mo_hw_scan(struct ieee80211_hw *, struct ieee80211_vif *,
struct ieee80211_scan_request *);
void lkpi_80211_mo_cancel_hw_scan(struct ieee80211_hw *, struct ieee80211_vif *);
void lkpi_80211_mo_sw_scan_complete(struct ieee80211_hw *, struct ieee80211_vif *);
void lkpi_80211_mo_sw_scan_start(struct ieee80211_hw *, struct ieee80211_vif *,
const u8 *);
u64 lkpi_80211_mo_prepare_multicast(struct ieee80211_hw *,
struct netdev_hw_addr_list *);
void lkpi_80211_mo_configure_filter(struct ieee80211_hw *, unsigned int,
unsigned int *, u64);
int lkpi_80211_mo_sta_state(struct ieee80211_hw *, struct ieee80211_vif *,
struct lkpi_sta *, enum ieee80211_sta_state);
int lkpi_80211_mo_config(struct ieee80211_hw *, uint32_t);
int lkpi_80211_mo_assign_vif_chanctx(struct ieee80211_hw *, struct ieee80211_vif *,
struct ieee80211_bss_conf *, struct ieee80211_chanctx_conf *);
void lkpi_80211_mo_unassign_vif_chanctx(struct ieee80211_hw *, struct ieee80211_vif *,
struct ieee80211_bss_conf *, struct ieee80211_chanctx_conf *);
int lkpi_80211_mo_add_chanctx(struct ieee80211_hw *, struct ieee80211_chanctx_conf *);
void lkpi_80211_mo_change_chanctx(struct ieee80211_hw *,
struct ieee80211_chanctx_conf *, uint32_t);
void lkpi_80211_mo_remove_chanctx(struct ieee80211_hw *,
struct ieee80211_chanctx_conf *);
void lkpi_80211_mo_vif_cfg_changed(struct ieee80211_hw *, struct ieee80211_vif *,
uint64_t, bool);
void lkpi_80211_mo_link_info_changed(struct ieee80211_hw *, struct ieee80211_vif *,
struct ieee80211_bss_conf *, uint64_t, uint8_t, bool);
void lkpi_80211_mo_bss_info_changed(struct ieee80211_hw *, struct ieee80211_vif *,
struct ieee80211_bss_conf *, uint64_t);
int lkpi_80211_mo_conf_tx(struct ieee80211_hw *, struct ieee80211_vif *,
uint32_t, uint16_t, const struct ieee80211_tx_queue_params *);
void lkpi_80211_mo_flush(struct ieee80211_hw *, struct ieee80211_vif *,
uint32_t, bool);
void lkpi_80211_mo_mgd_prepare_tx(struct ieee80211_hw *, struct ieee80211_vif *,
struct ieee80211_prep_tx_info *);
void lkpi_80211_mo_mgd_complete_tx(struct ieee80211_hw *, struct ieee80211_vif *,
struct ieee80211_prep_tx_info *);
void lkpi_80211_mo_tx(struct ieee80211_hw *, struct ieee80211_tx_control *,
struct sk_buff *);
void lkpi_80211_mo_wake_tx_queue(struct ieee80211_hw *, struct ieee80211_txq *,
bool);
void lkpi_80211_mo_sync_rx_queues(struct ieee80211_hw *);
void lkpi_80211_mo_sta_pre_rcu_remove(struct ieee80211_hw *,
struct ieee80211_vif *, struct ieee80211_sta *);
int lkpi_80211_mo_set_key(struct ieee80211_hw *, enum set_key_cmd,
struct ieee80211_vif *, struct ieee80211_sta *,
struct ieee80211_key_conf *);
int lkpi_80211_mo_ampdu_action(struct ieee80211_hw *, struct ieee80211_vif *,
struct ieee80211_ampdu_params *);
int lkpi_80211_mo_sta_statistics(struct ieee80211_hw *, struct ieee80211_vif *,
struct ieee80211_sta *, struct station_info *);
#endif