824 lines
23 KiB
C
824 lines
23 KiB
C
|
/* $OpenBSD: if_iwxvar.h,v 1.41 2023/03/06 11:53:24 stsp Exp $ */
|
||
|
|
||
|
/*
|
||
|
* Copyright (c) 2014 genua mbh <info@genua.de>
|
||
|
* Copyright (c) 2014 Fixup Software Ltd.
|
||
|
*
|
||
|
* Permission to use, copy, modify, and distribute this software for any
|
||
|
* purpose with or without fee is hereby granted, provided that the above
|
||
|
* copyright notice and this permission notice appear in all copies.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
/*-
|
||
|
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
|
||
|
* which were used as the reference documentation for this implementation.
|
||
|
*
|
||
|
******************************************************************************
|
||
|
*
|
||
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||
|
* redistributing this file, you may do so under either license.
|
||
|
*
|
||
|
* GPL LICENSE SUMMARY
|
||
|
*
|
||
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of version 2 of the GNU General Public License as
|
||
|
* published by the Free Software Foundation.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* General Public License for more details.
|
||
|
*
|
||
|
* BSD LICENSE
|
||
|
*
|
||
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
*
|
||
|
* * Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* * Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in
|
||
|
* the documentation and/or other materials provided with the
|
||
|
* distribution.
|
||
|
* * Neither the name Intel Corporation nor the names of its
|
||
|
* contributors may be used to endorse or promote products derived
|
||
|
* from this software without specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
|
||
|
/*-
|
||
|
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
|
||
|
*
|
||
|
* Permission to use, copy, modify, and distribute this software for any
|
||
|
* purpose with or without fee is hereby granted, provided that the above
|
||
|
* copyright notice and this permission notice appear in all copies.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
struct iwx_rx_radiotap_header {
|
||
|
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;
|
||
|
|
||
|
#define IWX_RX_RADIOTAP_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 iwx_tx_radiotap_header {
|
||
|
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 IWX_TX_RADIOTAP_PRESENT \
|
||
|
((1 << IEEE80211_RADIOTAP_FLAGS) | \
|
||
|
(1 << IEEE80211_RADIOTAP_RATE) | \
|
||
|
(1 << IEEE80211_RADIOTAP_CHANNEL))
|
||
|
|
||
|
#define IWX_UCODE_SECT_MAX 57
|
||
|
|
||
|
/*
|
||
|
* fw_status is used to determine if we've already parsed the firmware file
|
||
|
*
|
||
|
* In addition to the following, status < 0 ==> -error
|
||
|
*/
|
||
|
#define IWX_FW_STATUS_NONE 0
|
||
|
#define IWX_FW_STATUS_INPROGRESS 1
|
||
|
#define IWX_FW_STATUS_DONE 2
|
||
|
|
||
|
enum iwx_ucode_type {
|
||
|
IWX_UCODE_TYPE_REGULAR,
|
||
|
IWX_UCODE_TYPE_INIT,
|
||
|
IWX_UCODE_TYPE_WOW,
|
||
|
IWX_UCODE_TYPE_REGULAR_USNIFFER,
|
||
|
IWX_UCODE_TYPE_MAX
|
||
|
};
|
||
|
|
||
|
struct iwx_fw_info {
|
||
|
void *fw_rawdata;
|
||
|
size_t fw_rawsize;
|
||
|
int fw_status;
|
||
|
|
||
|
struct iwx_fw_sects {
|
||
|
struct iwx_fw_onesect {
|
||
|
void *fws_data;
|
||
|
uint32_t fws_len;
|
||
|
uint32_t fws_devoff;
|
||
|
} fw_sect[IWX_UCODE_SECT_MAX];
|
||
|
size_t fw_totlen;
|
||
|
int fw_count;
|
||
|
} fw_sects[IWX_UCODE_TYPE_MAX];
|
||
|
|
||
|
/* FW debug data parsed for driver usage */
|
||
|
int dbg_dest_tlv_init;
|
||
|
uint8_t *dbg_dest_ver;
|
||
|
uint8_t n_dest_reg;
|
||
|
struct iwx_fw_dbg_dest_tlv_v1 *dbg_dest_tlv_v1;
|
||
|
|
||
|
struct iwx_fw_dbg_conf_tlv *dbg_conf_tlv[IWX_FW_DBG_CONF_MAX];
|
||
|
size_t dbg_conf_tlv_len[IWX_FW_DBG_CONF_MAX];
|
||
|
struct iwx_fw_dbg_trigger_tlv *dbg_trigger_tlv[IWX_FW_DBG_TRIGGER_MAX];
|
||
|
size_t dbg_trigger_tlv_len[IWX_FW_DBG_TRIGGER_MAX];
|
||
|
struct iwx_fw_dbg_mem_seg_tlv *dbg_mem_tlv;
|
||
|
size_t n_mem_tlv;
|
||
|
|
||
|
/* Copy of firmware image loader found in file. */
|
||
|
uint8_t *iml;
|
||
|
size_t iml_len;
|
||
|
};
|
||
|
|
||
|
struct iwx_nvm_data {
|
||
|
int n_hw_addrs;
|
||
|
uint8_t hw_addr[ETHER_ADDR_LEN];
|
||
|
|
||
|
int sku_cap_band_24GHz_enable;
|
||
|
int sku_cap_band_52GHz_enable;
|
||
|
int sku_cap_11n_enable;
|
||
|
int sku_cap_11ac_enable;
|
||
|
int sku_cap_11ax_enable;
|
||
|
int sku_cap_amt_enable;
|
||
|
int sku_cap_ipan_enable;
|
||
|
int sku_cap_mimo_disable;
|
||
|
int lar_enabled;
|
||
|
|
||
|
uint8_t valid_tx_ant, valid_rx_ant;
|
||
|
|
||
|
uint16_t nvm_version;
|
||
|
};
|
||
|
|
||
|
/* max bufs per tfd the driver will use */
|
||
|
#define IWX_MAX_CMD_TBS_PER_TFD 2
|
||
|
|
||
|
struct iwx_host_cmd {
|
||
|
const void *data[IWX_MAX_CMD_TBS_PER_TFD];
|
||
|
struct iwx_rx_packet *resp_pkt;
|
||
|
size_t resp_pkt_len;
|
||
|
unsigned long _rx_page_addr;
|
||
|
uint32_t _rx_page_order;
|
||
|
int handler_status;
|
||
|
|
||
|
uint32_t flags;
|
||
|
uint16_t len[IWX_MAX_CMD_TBS_PER_TFD];
|
||
|
uint8_t dataflags[IWX_MAX_CMD_TBS_PER_TFD];
|
||
|
uint32_t id;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* DMA glue is from iwn
|
||
|
*/
|
||
|
|
||
|
struct iwx_dma_info {
|
||
|
bus_dma_tag_t tag;
|
||
|
bus_dmamap_t map;
|
||
|
bus_dma_segment_t seg;
|
||
|
bus_addr_t paddr;
|
||
|
void *vaddr;
|
||
|
bus_size_t size;
|
||
|
};
|
||
|
|
||
|
#define IWX_TX_RING_COUNT IWX_DEFAULT_QUEUE_SIZE
|
||
|
#define IWX_TX_RING_LOMARK 192
|
||
|
#define IWX_TX_RING_HIMARK 224
|
||
|
|
||
|
struct iwx_tx_data {
|
||
|
bus_dmamap_t map;
|
||
|
bus_addr_t cmd_paddr;
|
||
|
struct mbuf *m;
|
||
|
struct iwx_node *in;
|
||
|
int flags;
|
||
|
#define IWX_TXDATA_FLAG_CMD_IS_NARROW 0x01
|
||
|
};
|
||
|
|
||
|
struct iwx_tx_ring {
|
||
|
struct iwx_dma_info desc_dma;
|
||
|
struct iwx_dma_info cmd_dma;
|
||
|
struct iwx_dma_info bc_tbl;
|
||
|
struct iwx_tfh_tfd *desc;
|
||
|
struct iwx_device_cmd *cmd;
|
||
|
struct iwx_tx_data data[IWX_TX_RING_COUNT];
|
||
|
int qid;
|
||
|
int queued;
|
||
|
int cur;
|
||
|
int cur_hw;
|
||
|
int tail;
|
||
|
int tail_hw;
|
||
|
int tid;
|
||
|
};
|
||
|
|
||
|
#define IWX_RX_MQ_RING_COUNT 512
|
||
|
/* Linux driver optionally uses 8k buffer */
|
||
|
#define IWX_RBUF_SIZE 4096
|
||
|
|
||
|
struct iwx_rx_data {
|
||
|
struct mbuf *m;
|
||
|
bus_dmamap_t map;
|
||
|
};
|
||
|
|
||
|
struct iwx_rx_ring {
|
||
|
struct iwx_dma_info free_desc_dma;
|
||
|
struct iwx_dma_info stat_dma;
|
||
|
struct iwx_dma_info used_desc_dma;
|
||
|
void *desc;
|
||
|
struct iwx_rb_status *stat;
|
||
|
struct iwx_rx_data data[IWX_RX_MQ_RING_COUNT];
|
||
|
int cur;
|
||
|
};
|
||
|
|
||
|
#define IWX_FLAG_USE_ICT 0x01 /* using Interrupt Cause Table */
|
||
|
#define IWX_FLAG_RFKILL 0x02 /* radio kill switch is set */
|
||
|
#define IWX_FLAG_SCANNING 0x04 /* scan in progress */
|
||
|
#define IWX_FLAG_MAC_ACTIVE 0x08 /* MAC context added to firmware */
|
||
|
#define IWX_FLAG_BINDING_ACTIVE 0x10 /* MAC->PHY binding added to firmware */
|
||
|
#define IWX_FLAG_STA_ACTIVE 0x20 /* AP added to firmware station table */
|
||
|
#define IWX_FLAG_TE_ACTIVE 0x40 /* time event is scheduled */
|
||
|
#define IWX_FLAG_HW_ERR 0x80 /* hardware error occurred */
|
||
|
#define IWX_FLAG_SHUTDOWN 0x100 /* shutting down; new tasks forbidden */
|
||
|
#define IWX_FLAG_BGSCAN 0x200 /* background scan in progress */
|
||
|
#define IWX_FLAG_TXFLUSH 0x400 /* Tx queue flushing in progress */
|
||
|
|
||
|
struct iwx_ucode_status {
|
||
|
uint32_t uc_lmac_error_event_table[2];
|
||
|
uint32_t uc_umac_error_event_table;
|
||
|
uint32_t uc_log_event_table;
|
||
|
unsigned int error_event_table_tlv_status;
|
||
|
|
||
|
int uc_ok;
|
||
|
int uc_intr;
|
||
|
};
|
||
|
|
||
|
#define IWX_ERROR_EVENT_TABLE_LMAC1 (1 << 0)
|
||
|
#define IWX_ERROR_EVENT_TABLE_LMAC2 (1 << 1)
|
||
|
#define IWX_ERROR_EVENT_TABLE_UMAC (1 << 2)
|
||
|
|
||
|
#define IWX_CMD_RESP_MAX PAGE_SIZE
|
||
|
|
||
|
/* lower blocks contain EEPROM image and calibration data */
|
||
|
#define IWX_OTP_LOW_IMAGE_SIZE_FAMILY_7000 16384
|
||
|
#define IWX_OTP_LOW_IMAGE_SIZE_FAMILY_8000 32768
|
||
|
|
||
|
#define IWX_TE_SESSION_PROTECTION_MAX_TIME_MS 1000
|
||
|
#define IWX_TE_SESSION_PROTECTION_MIN_TIME_MS 400
|
||
|
|
||
|
enum IWX_CMD_MODE {
|
||
|
IWX_CMD_ASYNC = (1 << 0),
|
||
|
IWX_CMD_WANT_RESP = (1 << 1),
|
||
|
IWX_CMD_SEND_IN_RFKILL = (1 << 2),
|
||
|
};
|
||
|
enum iwx_hcmd_dataflag {
|
||
|
IWX_HCMD_DFL_NOCOPY = (1 << 0),
|
||
|
IWX_HCMD_DFL_DUP = (1 << 1),
|
||
|
};
|
||
|
|
||
|
#define IWX_NUM_PAPD_CH_GROUPS 9
|
||
|
#define IWX_NUM_TXP_CH_GROUPS 9
|
||
|
|
||
|
struct iwx_phy_ctxt {
|
||
|
uint16_t id;
|
||
|
uint16_t color;
|
||
|
uint32_t ref;
|
||
|
struct ieee80211_channel *channel;
|
||
|
uint8_t sco; /* 40 MHz secondary channel offset */
|
||
|
uint8_t vht_chan_width;
|
||
|
};
|
||
|
|
||
|
struct iwx_bf_data {
|
||
|
int bf_enabled; /* filtering */
|
||
|
int ba_enabled; /* abort */
|
||
|
int ave_beacon_signal;
|
||
|
int last_cqm_event;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* struct iwx_self_init_dram - dram data used by self init process
|
||
|
* @fw: lmac and umac dram data
|
||
|
* @lmac_cnt: number of lmac sections in fw image
|
||
|
* @umac_cnt: number of umac sections in fw image
|
||
|
* @paging: paging dram data
|
||
|
* @paging_cnt: number of paging sections needed by fw image
|
||
|
*/
|
||
|
struct iwx_self_init_dram {
|
||
|
struct iwx_dma_info *fw;
|
||
|
int lmac_cnt;
|
||
|
int umac_cnt;
|
||
|
struct iwx_dma_info *paging;
|
||
|
int paging_cnt;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* struct iwx_reorder_buffer - per ra/tid/queue reorder buffer
|
||
|
* @head_sn: reorder window head sn
|
||
|
* @num_stored: number of mpdus stored in the buffer
|
||
|
* @buf_size: the reorder buffer size as set by the last addba request
|
||
|
* @queue: queue of this reorder buffer
|
||
|
* @last_amsdu: track last ASMDU SN for duplication detection
|
||
|
* @last_sub_index: track ASMDU sub frame index for duplication detection
|
||
|
* @reorder_timer: timer for frames are in the reorder buffer. For AMSDU
|
||
|
* it is the time of last received sub-frame
|
||
|
* @removed: prevent timer re-arming
|
||
|
* @valid: reordering is valid for this queue
|
||
|
* @consec_oldsn_drops: consecutive drops due to old SN
|
||
|
* @consec_oldsn_ampdu_gp2: A-MPDU GP2 timestamp to track
|
||
|
* when to apply old SN consecutive drop workaround
|
||
|
* @consec_oldsn_prev_drop: track whether or not an MPDU
|
||
|
* that was single/part of the previous A-MPDU was
|
||
|
* dropped due to old SN
|
||
|
*/
|
||
|
struct iwx_reorder_buffer {
|
||
|
uint16_t head_sn;
|
||
|
uint16_t num_stored;
|
||
|
uint16_t buf_size;
|
||
|
uint16_t last_amsdu;
|
||
|
uint8_t last_sub_index;
|
||
|
struct timeout reorder_timer;
|
||
|
int removed;
|
||
|
int valid;
|
||
|
unsigned int consec_oldsn_drops;
|
||
|
uint32_t consec_oldsn_ampdu_gp2;
|
||
|
unsigned int consec_oldsn_prev_drop;
|
||
|
#define IWX_AMPDU_CONSEC_DROPS_DELBA 10
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* struct iwx_reorder_buf_entry - reorder buffer entry per frame sequence number
|
||
|
* @frames: list of mbufs stored (A-MSDU subframes share a sequence number)
|
||
|
* @reorder_time: time the packet was stored in the reorder buffer
|
||
|
*/
|
||
|
struct iwx_reorder_buf_entry {
|
||
|
struct mbuf_list frames;
|
||
|
struct timeval reorder_time;
|
||
|
uint32_t rx_pkt_status;
|
||
|
int chanidx;
|
||
|
int is_shortpre;
|
||
|
uint32_t rate_n_flags;
|
||
|
uint32_t device_timestamp;
|
||
|
struct ieee80211_rxinfo rxi;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* struct iwx_rxba_data - BA session data
|
||
|
* @sta_id: station id
|
||
|
* @tid: tid of the session
|
||
|
* @baid: baid of the session
|
||
|
* @timeout: the timeout set in the addba request
|
||
|
* @entries_per_queue: # of buffers per queue
|
||
|
* @last_rx: last rx timestamp, updated only if timeout passed from last update
|
||
|
* @session_timer: timer to check if BA session expired, runs at 2 * timeout
|
||
|
* @sc: softc pointer, needed for timer context
|
||
|
* @reorder_buf: reorder buffer
|
||
|
* @reorder_buf_data: buffered frames, one entry per sequence number
|
||
|
*/
|
||
|
struct iwx_rxba_data {
|
||
|
uint8_t sta_id;
|
||
|
uint8_t tid;
|
||
|
uint8_t baid;
|
||
|
uint16_t timeout;
|
||
|
uint16_t entries_per_queue;
|
||
|
struct timeval last_rx;
|
||
|
struct timeout session_timer;
|
||
|
struct iwx_softc *sc;
|
||
|
struct iwx_reorder_buffer reorder_buf;
|
||
|
struct iwx_reorder_buf_entry entries[IEEE80211_BA_MAX_WINSZ];
|
||
|
};
|
||
|
|
||
|
static inline struct iwx_rxba_data *
|
||
|
iwx_rxba_data_from_reorder_buf(struct iwx_reorder_buffer *buf)
|
||
|
{
|
||
|
return (void *)((uint8_t *)buf -
|
||
|
offsetof(struct iwx_rxba_data, reorder_buf));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* struct iwx_rxq_dup_data - per station per rx queue data
|
||
|
* @last_seq: last sequence per tid for duplicate packet detection
|
||
|
* @last_sub_frame: last subframe packet
|
||
|
*/
|
||
|
struct iwx_rxq_dup_data {
|
||
|
uint16_t last_seq[IWX_MAX_TID_COUNT + 1];
|
||
|
uint8_t last_sub_frame[IWX_MAX_TID_COUNT + 1];
|
||
|
};
|
||
|
|
||
|
struct iwx_setkey_task_arg {
|
||
|
int sta_id;
|
||
|
struct ieee80211_node *ni;
|
||
|
struct ieee80211_key *k;
|
||
|
};
|
||
|
|
||
|
struct iwx_ba_task_data {
|
||
|
uint32_t start_tidmask;
|
||
|
uint32_t stop_tidmask;
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Device configuration parameters which cannot be detected based on
|
||
|
* PCI vendor/product ID alone.
|
||
|
*/
|
||
|
struct iwx_device_cfg {
|
||
|
const char *fw_name;
|
||
|
const char *pnvm_name;
|
||
|
int tx_with_siso_diversity;
|
||
|
int uhb_supported;
|
||
|
int xtal_latency;
|
||
|
int low_latency_xtal;
|
||
|
};
|
||
|
|
||
|
/* Firmware listed here must be available in fw_update(8). */
|
||
|
#define IWX_CC_A_FW "iwx-cc-a0-77"
|
||
|
#define IWX_TY_A_GF_A_FW "iwx-ty-a0-gf-a0-77"
|
||
|
#define IWX_TY_A_GF_A_PNVM "iwx-ty-a0-gf-a0.pnvm"
|
||
|
#define IWX_QU_B_HR_B_FW "iwx-Qu-b0-hr-b0-77"
|
||
|
#define IWX_QU_B_JF_B_FW "iwx-Qu-b0-jf-b0-77"
|
||
|
#define IWX_QU_C_HR_B_FW "iwx-Qu-c0-hr-b0-77"
|
||
|
#define IWX_QU_C_JF_B_FW "iwx-Qu-c0-jf-b0-77"
|
||
|
#define IWX_QUZ_A_HR_B_FW "iwx-QuZ-a0-hr-b0-77"
|
||
|
#define IWX_QUZ_A_JF_B_FW "iwx-QuZ-a0-jf-b0-77"
|
||
|
#define IWX_SO_A_GF_A_FW "iwx-so-a0-gf-a0-77"
|
||
|
#define IWX_SO_A_GF_A_PNVM "iwx-so-a0-gf-a0.pnvm"
|
||
|
#define IWX_SO_A_GF4_A_FW "iwx-so-a0-gf4-a0-77"
|
||
|
#define IWX_SO_A_GF4_A_PNVM "iwx-so-a0-gf4-a0.pnvm"
|
||
|
#define IWX_SO_A_HR_B_FW "iwx-so-a0-hr-b0-77"
|
||
|
#define IWX_SO_A_JF_B_FW "iwx-so-a0-jf-b0-77"
|
||
|
|
||
|
const struct iwx_device_cfg iwx_9560_quz_a0_jf_b0_cfg = {
|
||
|
.fw_name = IWX_QUZ_A_JF_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_9560_qu_c0_jf_b0_cfg = {
|
||
|
.fw_name = IWX_QU_C_JF_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_qu_b0_hr1_b0 = {
|
||
|
.fw_name = IWX_QU_B_HR_B_FW,
|
||
|
.tx_with_siso_diversity = true,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_qu_b0_hr_b0 = {
|
||
|
.fw_name = IWX_QU_B_HR_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_ax201_cfg_qu_hr = {
|
||
|
.fw_name = IWX_QU_B_HR_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_qu_c0_hr1_b0 = {
|
||
|
.fw_name = IWX_QU_C_HR_B_FW,
|
||
|
.tx_with_siso_diversity = true,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_qu_c0_hr_b0 = {
|
||
|
.fw_name = IWX_QU_C_HR_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_ax201_cfg_qu_c0_hr_b0 = {
|
||
|
.fw_name = IWX_QU_C_HR_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_quz_a0_hr1_b0 = {
|
||
|
.fw_name = IWX_QUZ_A_HR_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_ax201_cfg_quz_hr = {
|
||
|
.fw_name = IWX_QUZ_A_HR_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_cfg_so_a0_hr_b0 = {
|
||
|
.fw_name = IWX_SO_A_HR_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_cfg_quz_a0_hr_b0 = {
|
||
|
.fw_name = IWX_QUZ_A_HR_B_FW,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_2ax_cfg_so_gf_a0 = {
|
||
|
.fw_name = IWX_SO_A_GF_A_FW,
|
||
|
.pnvm_name = IWX_SO_A_GF_A_PNVM,
|
||
|
.uhb_supported = 1,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_2ax_cfg_so_gf_a0_long = {
|
||
|
.fw_name = IWX_SO_A_GF_A_FW,
|
||
|
.pnvm_name = IWX_SO_A_GF_A_PNVM,
|
||
|
.uhb_supported = 1,
|
||
|
.xtal_latency = 12000,
|
||
|
.low_latency_xtal = 1,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_2ax_cfg_so_gf4_a0 = {
|
||
|
.fw_name = IWX_SO_A_GF4_A_FW,
|
||
|
.pnvm_name = IWX_SO_A_GF4_A_PNVM,
|
||
|
.uhb_supported = 1,
|
||
|
.xtal_latency = 12000,
|
||
|
.low_latency_xtal = 1,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_2ax_cfg_so_gf4_a0_long = {
|
||
|
.fw_name = IWX_SO_A_GF4_A_FW,
|
||
|
.pnvm_name = IWX_SO_A_GF4_A_PNVM,
|
||
|
.uhb_supported = 1,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_2ax_cfg_ty_gf_a0 = {
|
||
|
.fw_name = IWX_TY_A_GF_A_FW,
|
||
|
.pnvm_name = IWX_TY_A_GF_A_PNVM,
|
||
|
};
|
||
|
|
||
|
const struct iwx_device_cfg iwx_2ax_cfg_so_jf_b0 = {
|
||
|
.fw_name = IWX_SO_A_JF_B_FW,
|
||
|
};
|
||
|
|
||
|
#define IWX_CFG_ANY (~0)
|
||
|
|
||
|
#define IWX_CFG_MAC_TYPE_QU 0x33
|
||
|
#define IWX_CFG_MAC_TYPE_QUZ 0x35
|
||
|
#define IWX_CFG_MAC_TYPE_QNJ 0x36
|
||
|
#define IWX_CFG_MAC_TYPE_SO 0x37
|
||
|
#define IWX_CFG_MAC_TYPE_SNJ 0x42
|
||
|
#define IWX_CFG_MAC_TYPE_SOF 0x43
|
||
|
#define IWX_CFG_MAC_TYPE_MA 0x44
|
||
|
#define IWX_CFG_MAC_TYPE_BZ 0x46
|
||
|
#define IWX_CFG_MAC_TYPE_GL 0x47
|
||
|
|
||
|
#define IWX_CFG_RF_TYPE_JF2 0x105
|
||
|
#define IWX_CFG_RF_TYPE_JF1 0x108
|
||
|
#define IWX_CFG_RF_TYPE_HR2 0x10a
|
||
|
#define IWX_CFG_RF_TYPE_HR1 0x10c
|
||
|
#define IWX_CFG_RF_TYPE_GF 0x10d
|
||
|
#define IWX_CFG_RF_TYPE_MR 0x110
|
||
|
#define IWX_CFG_RF_TYPE_MS 0x111
|
||
|
#define IWX_CFG_RF_TYPE_FM 0x112
|
||
|
|
||
|
#define IWX_CFG_RF_ID_JF 0x3
|
||
|
#define IWX_CFG_RF_ID_JF1 0x6
|
||
|
#define IWX_CFG_RF_ID_JF1_DIV 0xa
|
||
|
|
||
|
#define IWX_CFG_NO_160 0x1
|
||
|
#define IWX_CFG_160 0x0
|
||
|
|
||
|
#define IWX_CFG_CORES_BT 0x0
|
||
|
|
||
|
#define IWX_CFG_NO_CDB 0x0
|
||
|
#define IWX_CFG_CDB 0x1
|
||
|
|
||
|
#define IWX_SUBDEVICE_RF_ID(subdevice) ((uint16_t)((subdevice) & 0x00f0) >> 4)
|
||
|
#define IWX_SUBDEVICE_NO_160(subdevice) ((uint16_t)((subdevice) & 0x0200) >> 9)
|
||
|
#define IWX_SUBDEVICE_CORES(subdevice) ((uint16_t)((subdevice) & 0x1c00) >> 10)
|
||
|
|
||
|
struct iwx_softc {
|
||
|
struct device sc_dev;
|
||
|
struct ieee80211com sc_ic;
|
||
|
int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int);
|
||
|
int sc_newstate_pending;
|
||
|
int attached;
|
||
|
|
||
|
struct task init_task; /* NB: not reference-counted */
|
||
|
struct refcnt task_refs;
|
||
|
struct task newstate_task;
|
||
|
enum ieee80211_state ns_nstate;
|
||
|
int ns_arg;
|
||
|
|
||
|
/* Task for firmware BlockAck setup/teardown and its arguments. */
|
||
|
struct task ba_task;
|
||
|
struct iwx_ba_task_data ba_rx;
|
||
|
struct iwx_ba_task_data ba_tx;
|
||
|
|
||
|
/* Task for setting encryption keys and its arguments. */
|
||
|
struct task setkey_task;
|
||
|
/*
|
||
|
* At present we need to process at most two keys at once:
|
||
|
* Our pairwise key and a group key.
|
||
|
* When hostap mode is implemented this array needs to grow or
|
||
|
* it might become a bottleneck for associations that occur at
|
||
|
* roughly the same time.
|
||
|
*/
|
||
|
struct iwx_setkey_task_arg setkey_arg[2];
|
||
|
int setkey_cur;
|
||
|
int setkey_tail;
|
||
|
int setkey_nkeys;
|
||
|
|
||
|
/* Task for ERP/HT prot/slot-time/EDCA updates. */
|
||
|
struct task mac_ctxt_task;
|
||
|
|
||
|
/* Task for HT 20/40 MHz channel width updates. */
|
||
|
struct task phy_ctxt_task;
|
||
|
|
||
|
bus_space_tag_t sc_st;
|
||
|
bus_space_handle_t sc_sh;
|
||
|
bus_size_t sc_sz;
|
||
|
bus_dma_tag_t sc_dmat;
|
||
|
pci_product_id_t sc_pid;
|
||
|
pci_chipset_tag_t sc_pct;
|
||
|
pcitag_t sc_pcitag;
|
||
|
const void *sc_ih;
|
||
|
int sc_msix;
|
||
|
|
||
|
/* TX/RX rings. */
|
||
|
struct iwx_tx_ring txq[IWX_NUM_TX_QUEUES];
|
||
|
struct iwx_rx_ring rxq;
|
||
|
int qfullmsk;
|
||
|
int qenablemsk;
|
||
|
int first_data_qid;
|
||
|
int aggqid[IEEE80211_NUM_TID];
|
||
|
int max_tfd_queue_size;
|
||
|
|
||
|
int sc_sf_state;
|
||
|
|
||
|
/* ICT table. */
|
||
|
struct iwx_dma_info ict_dma;
|
||
|
int ict_cur;
|
||
|
|
||
|
int sc_hw_rev;
|
||
|
#define IWX_SILICON_A_STEP 0
|
||
|
#define IWX_SILICON_B_STEP 1
|
||
|
#define IWX_SILICON_C_STEP 2
|
||
|
#define IWX_SILICON_Z_STEP 0xf
|
||
|
int sc_hw_id;
|
||
|
int sc_hw_rf_id;
|
||
|
int sc_device_family;
|
||
|
#define IWX_DEVICE_FAMILY_22000 1
|
||
|
#define IWX_DEVICE_FAMILY_AX210 2
|
||
|
uint32_t sc_sku_id[3];
|
||
|
uint32_t mac_addr_from_csr;
|
||
|
|
||
|
struct iwx_dma_info ctxt_info_dma;
|
||
|
struct iwx_self_init_dram init_dram;
|
||
|
struct iwx_dma_info prph_scratch_dma;
|
||
|
struct iwx_dma_info prph_info_dma;
|
||
|
struct iwx_dma_info iml_dma;
|
||
|
struct iwx_dma_info pnvm_dma;
|
||
|
uint32_t sc_pnvm_ver;
|
||
|
|
||
|
int sc_fw_chunk_done;
|
||
|
int sc_init_complete;
|
||
|
#define IWX_INIT_COMPLETE 0x01
|
||
|
#define IWX_CALIB_COMPLETE 0x02
|
||
|
#define IWX_PNVM_COMPLETE 0x04
|
||
|
|
||
|
struct iwx_ucode_status sc_uc;
|
||
|
char sc_fwver[32];
|
||
|
|
||
|
int sc_capaflags;
|
||
|
int sc_capa_max_probe_len;
|
||
|
int sc_capa_n_scan_channels;
|
||
|
uint8_t sc_ucode_api[howmany(IWX_NUM_UCODE_TLV_API, NBBY)];
|
||
|
uint8_t sc_enabled_capa[howmany(IWX_NUM_UCODE_TLV_CAPA, NBBY)];
|
||
|
#define IWX_MAX_FW_CMD_VERSIONS 704
|
||
|
struct iwx_fw_cmd_version cmd_versions[IWX_MAX_FW_CMD_VERSIONS];
|
||
|
int n_cmd_versions;
|
||
|
int sc_rate_n_flags_version;
|
||
|
|
||
|
int sc_intmask;
|
||
|
int sc_flags;
|
||
|
|
||
|
uint32_t sc_fh_init_mask;
|
||
|
uint32_t sc_hw_init_mask;
|
||
|
uint32_t sc_fh_mask;
|
||
|
uint32_t sc_hw_mask;
|
||
|
|
||
|
int sc_generation;
|
||
|
|
||
|
struct rwlock ioctl_rwl;
|
||
|
|
||
|
int sc_cap_off; /* PCIe caps */
|
||
|
|
||
|
const char *sc_fwname;
|
||
|
struct iwx_fw_info sc_fw;
|
||
|
struct iwx_dma_info fw_mon;
|
||
|
int sc_fw_phy_config;
|
||
|
struct iwx_tlv_calib_ctrl sc_default_calib[IWX_UCODE_TYPE_MAX];
|
||
|
|
||
|
struct iwx_nvm_data sc_nvm;
|
||
|
struct iwx_bf_data sc_bf;
|
||
|
const char *sc_pnvm_name;
|
||
|
|
||
|
int sc_tx_timer[IWX_NUM_TX_QUEUES];
|
||
|
int sc_rx_ba_sessions;
|
||
|
|
||
|
struct task bgscan_done_task;
|
||
|
struct ieee80211_node_switch_bss_arg *bgscan_unref_arg;
|
||
|
size_t bgscan_unref_arg_size;
|
||
|
|
||
|
int sc_scan_last_antenna;
|
||
|
|
||
|
int sc_staid;
|
||
|
int sc_nodecolor;
|
||
|
|
||
|
uint8_t *sc_cmd_resp_pkt[IWX_TX_RING_COUNT];
|
||
|
size_t sc_cmd_resp_len[IWX_TX_RING_COUNT];
|
||
|
int sc_nic_locks;
|
||
|
|
||
|
struct taskq *sc_nswq;
|
||
|
|
||
|
struct iwx_rx_phy_info sc_last_phy_info;
|
||
|
int sc_ampdu_ref;
|
||
|
struct iwx_rxba_data sc_rxba_data[IWX_MAX_BAID];
|
||
|
|
||
|
uint32_t sc_time_event_uid;
|
||
|
|
||
|
/* phy contexts. we only use the first one */
|
||
|
struct iwx_phy_ctxt sc_phyctxt[IWX_NUM_PHY_CTX];
|
||
|
|
||
|
struct iwx_notif_statistics sc_stats;
|
||
|
int sc_noise;
|
||
|
|
||
|
int sc_pm_support;
|
||
|
int sc_ltr_enabled;
|
||
|
|
||
|
int sc_integrated;
|
||
|
int sc_tx_with_siso_diversity;
|
||
|
int sc_max_tfd_queue_size;
|
||
|
int sc_ltr_delay;
|
||
|
int sc_xtal_latency;
|
||
|
int sc_low_latency_xtal;
|
||
|
int sc_uhb_supported;
|
||
|
int sc_umac_prph_offset;
|
||
|
int sc_imr_enabled;
|
||
|
|
||
|
#if NBPFILTER > 0
|
||
|
caddr_t sc_drvbpf;
|
||
|
|
||
|
union {
|
||
|
struct iwx_rx_radiotap_header th;
|
||
|
uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
|
||
|
} sc_rxtapu;
|
||
|
#define sc_rxtap sc_rxtapu.th
|
||
|
int sc_rxtap_len;
|
||
|
|
||
|
union {
|
||
|
struct iwx_tx_radiotap_header th;
|
||
|
uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
|
||
|
} sc_txtapu;
|
||
|
#define sc_txtap sc_txtapu.th
|
||
|
int sc_txtap_len;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
struct iwx_node {
|
||
|
struct ieee80211_node in_ni;
|
||
|
struct iwx_phy_ctxt *in_phyctxt;
|
||
|
uint8_t in_macaddr[ETHER_ADDR_LEN];
|
||
|
|
||
|
uint16_t in_id;
|
||
|
uint16_t in_color;
|
||
|
|
||
|
struct iwx_rxq_dup_data dup_data;
|
||
|
|
||
|
int in_flags;
|
||
|
#define IWX_NODE_FLAG_HAVE_PAIRWISE_KEY 0x01
|
||
|
#define IWX_NODE_FLAG_HAVE_GROUP_KEY 0x02
|
||
|
};
|
||
|
#define IWX_STATION_ID 0
|
||
|
#define IWX_AUX_STA_ID 1
|
||
|
#define IWX_MONITOR_STA_ID 2
|
||
|
|
||
|
#define IWX_ICT_SIZE 4096
|
||
|
#define IWX_ICT_COUNT (IWX_ICT_SIZE / sizeof (uint32_t))
|
||
|
#define IWX_ICT_PADDR_SHIFT 12
|