/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*/
/* maximum number of virtual interfaces the driver supports * (including the main interface)
*/ #define WIL_MAX_VIFS 4
/** * extract bits [@b0:@b1] (inclusive) from the value @x * it should be @b0 <= @b1, or result is incorrect
*/ staticinline u32 WIL_GET_BITS(u32 x, int b0, int b1)
{ return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1);
}
struct wil_suspend_stats { struct wil_suspend_count_stats r_off; struct wil_suspend_count_stats r_on; unsignedlong rejected_by_device; /* only radio on */ unsignedlong rejected_by_host;
};
/* Calculate MAC buffer size for the firmware. It includes all overhead, * as it will go over the air, and need to be 8 byte aligned
*/ staticinline u32 wil_mtu2macbuf(u32 mtu)
{ return ALIGN(mtu + WIL_MAX_MPDU_OVERHEAD, 8);
}
/* MTU for Ethernet need to take into account 8-byte SNAP header * to be added when encapsulating Ethernet frame into 802.11
*/ #define WIL_MAX_ETH_MTU (IEEE80211_MAX_DATA_LEN_DMG - 8) /* Max supported by wil6210 value for interrupt threshold is 5sec. */ #define WIL6210_ITR_TRSH_MAX (5000000) #define WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT (13) /* usec */ #define WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT (13) /* usec */ #define WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT (500) /* usec */ #define WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT (500) /* usec */ #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ #define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000) #define WIL6210_SCAN_TO msecs_to_jiffies(10000) #define WIL6210_DISCONNECT_TO_MS (2000) #define WIL6210_RX_HIGH_TRSH_INIT (0) #define WIL6210_RX_HIGH_TRSH_DEFAULT \
(1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3)) #define WIL_MAX_DMG_AID 254 /* for DMG only 1-254 allowed (see * 802.11REVmc/D5.0, section 9.4.1.8)
*/ /* Hardware definitions begin */
/* Common representation of physical address in wil ring */ struct wil_ring_dma_addr {
__le32 addr_low;
__le16 addr_high;
} __packed;
struct fw_map {
u32 from; /* linker address - from, inclusive */
u32 to; /* linker address - to, exclusive */
u32 host; /* PCI/Host address - BAR0 + 0x880000 */ constchar *name; /* for debugfs */ bool fw; /* true if FW mapping, false if UCODE mapping */ bool crash_dump; /* true if should be dumped during crash dump */
};
/* array size should be in sync with actual definition in the wmi.c */ externconststruct fw_map sparrow_fw_mapping[SPARROW_FW_MAPPING_TABLE_SIZE]; externconststruct fw_map sparrow_d0_mac_rgf_ext; externconststruct fw_map talyn_fw_mapping[TALYN_FW_MAPPING_TABLE_SIZE]; externconststruct fw_map talyn_mb_fw_mapping[TALYN_MB_FW_MAPPING_TABLE_SIZE]; externstruct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
/** * mk_cidxtid - construct @cidxtid field * @cid: CID value * @tid: TID value * * @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID
*/ staticinline u8 mk_cidxtid(u8 cid, u8 tid)
{ return ((tid & 0xf) << 4) | (cid & 0xf);
}
/** * parse_cidxtid - parse @cidxtid field * @cid: store CID value here * @tid: store TID value here * * @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID
*/ staticinlinevoid parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid)
{
*cid = cidxtid & 0xf;
*tid = (cidxtid >> 4) & 0xf;
}
struct wil_desc_ring_rx_swtail { /* relevant for enhanced DMA only */
u32 *va;
dma_addr_t pa;
};
/** * A general ring structure, used for RX and TX. * In legacy DMA it represents the vring, * In enahnced DMA it represents the descriptor ring (vrings are handled by FW)
*/ struct wil_ring {
dma_addr_t pa; volatileunion wil_ring_desc *va;
u16 size; /* number of wil_ring_desc elements */
u32 swtail;
u32 swhead;
u32 hwtail; /* write here to inform hw */ struct wil_ctx *ctx; /* ctx[size] - software context */ struct wil_desc_ring_rx_swtail edma_rx_swtail; bool is_rx;
};
/** * Additional data for Rx ring. * Used for enhanced DMA RX chaining.
*/ struct wil_ring_rx_data { /* the skb being assembled */ struct sk_buff *skb; /* true if we are skipping a bad fragmented packet */ bool skipping;
u16 buff_size;
};
/** * Status ring structure, used for enhanced DMA completions for RX and TX.
*/ struct wil_status_ring {
dma_addr_t pa; void *va; /* pointer to ring_[tr]x_status elements */
u16 size; /* number of status elements */
size_t elem_size; /* status element size in bytes */
u32 swhead;
u32 hwtail; /* write here to inform hw */ bool is_rx;
u8 desc_rdy_pol; /* Expected descriptor ready bit polarity */ struct wil_ring_rx_data rx_data;
u32 invalid_buff_id_cnt; /* relevant only for RX */
};
/** * struct tx_rx_ops - different TX/RX ops for legacy and enhanced * DMA flow
*/ struct wil_txrx_ops { void (*configure_interrupt_moderation)(struct wil6210_priv *wil); /* TX ops */ int (*ring_init_tx)(struct wil6210_vif *vif, int ring_id, int size, int cid, int tid); void (*ring_fini_tx)(struct wil6210_priv *wil, struct wil_ring *ring); int (*ring_init_bcast)(struct wil6210_vif *vif, int id, int size); int (*tx_init)(struct wil6210_priv *wil); void (*tx_fini)(struct wil6210_priv *wil); int (*tx_desc_map)(union wil_tx_desc *desc, dma_addr_t pa,
u32 len, int ring_index); void (*tx_desc_unmap)(struct device *dev, union wil_tx_desc *desc, struct wil_ctx *ctx); int (*tx_ring_tso)(struct wil6210_priv *wil, struct wil6210_vif *vif, struct wil_ring *ring, struct sk_buff *skb); int (*tx_ring_modify)(struct wil6210_vif *vif, int ring_id, int cid, int tid);
irqreturn_t (*irq_tx)(int irq, void *cookie); /* RX ops */ int (*rx_init)(struct wil6210_priv *wil, uint ring_order); void (*rx_fini)(struct wil6210_priv *wil); int (*wmi_addba_rx_resp)(struct wil6210_priv *wil, u8 mid, u8 cid,
u8 tid, u8 token, u16 status, bool amsdu,
u16 agg_wsize, u16 timeout); void (*get_reorder_params)(struct wil6210_priv *wil, struct sk_buff *skb, int *tid, int *cid, int *mid, u16 *seq, int *mcast, int *retry); void (*get_netif_rx_params)(struct sk_buff *skb, int *cid, int *security); int (*rx_crypto_check)(struct wil6210_priv *wil, struct sk_buff *skb); int (*rx_error_check)(struct wil6210_priv *wil, struct sk_buff *skb, struct wil_net_stats *stats); bool (*is_rx_idle)(struct wil6210_priv *wil);
irqreturn_t (*irq_rx)(int irq, void *cookie);
};
/** * Additional data for Tx ring
*/ struct wil_ring_tx_data { bool dot1x_open; int enabled;
cycles_t idle, last_idle, begin;
u8 agg_wsize; /* agreed aggregation window, 0 - no agg */
u16 agg_timeout;
u8 agg_amsdu; bool addba_in_progress; /* if set, agg_xxx is for request in progress */
u8 mid;
spinlock_t lock;
};
enum { /* for wil6210_priv.status */
wil_status_fwready = 0, /* FW operational */
wil_status_dontscan,
wil_status_mbox_ready, /* MBOX structures ready */
wil_status_irqen, /* interrupts enabled - for debug */
wil_status_napi_en, /* NAPI enabled protected by wil->mutex */
wil_status_resetting, /* reset in progress */
wil_status_suspending, /* suspend in progress */
wil_status_suspended, /* suspend completed, device is suspended */
wil_status_resuming, /* resume in progress */
wil_status_last /* keep last */
};
struct pci_dev;
/** * struct tid_ampdu_rx - TID aggregation information (Rx). * * @reorder_buf: buffer to reorder incoming aggregated MPDUs * @last_rx: jiffies of last rx activity * @head_seq_num: head sequence number in reordering buffer. * @stored_mpdu_num: number of MPDUs in reordering buffer * @ssn: Starting Sequence Number expected to be aggregated. * @buf_size: buffer size for incoming A-MPDUs * @ssn_last_drop: SSN of the last dropped frame * @total: total number of processed incoming frames * @drop_dup: duplicate frames dropped for this reorder buffer * @drop_old: old frames dropped for this reorder buffer * @first_time: true when this buffer used 1-st time * @mcast_last_seq: sequence number (SN) of last received multicast packet * @drop_dup_mcast: duplicate multicast frames dropped for this reorder buffer
*/ struct wil_tid_ampdu_rx { struct sk_buff **reorder_buf; unsignedlong last_rx;
u16 head_seq_num;
u16 stored_mpdu_num;
u16 ssn;
u16 buf_size;
u16 ssn_last_drop; unsignedlonglong total; /* frames processed */ unsignedlonglong drop_dup; unsignedlonglong drop_old; bool first_time; /* is it 1-st time this buffer used? */
u16 mcast_last_seq; /* multicast dup detection */ unsignedlonglong drop_dup_mcast;
};
/** * struct wil_tid_crypto_rx_single - TID crypto information (Rx). * * @pn: GCMP PN for the session * @key_set: valid key present
*/ struct wil_tid_crypto_rx_single {
u8 pn[IEEE80211_GCMP_PN_LEN]; bool key_set;
};
struct pmc_ctx { /* alloc, free, and read operations must own the lock */ struct mutex lock; struct vring_tx_desc *pring_va;
dma_addr_t pring_pa; struct desc_alloc_info *descriptors; int last_cmd_status; int num_descriptors; int descriptor_size;
};
struct wil6210_vif { struct wireless_dev wdev; struct net_device *ndev; struct wil6210_priv *wil;
u8 mid;
DECLARE_BITMAP(status, wil_vif_status_last);
u32 privacy; /* secure connection? */
u16 channel; /* relevant in AP mode */
u8 wmi_edmg_channel; /* relevant in AP mode */
u8 hidden_ssid; /* relevant in AP mode */
u32 ap_isolate; /* no intra-BSS communication */ bool pbss; int bi;
u8 *proberesp, *proberesp_ies, *assocresp_ies;
size_t proberesp_len, proberesp_ies_len, assocresp_ies_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
size_t ssid_len;
u8 gtk_index;
u8 gtk[WMI_MAX_KEY_LEN];
size_t gtk_len; int bcast_ring; struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */ int locally_generated_disc; /* relevant in STA mode */ struct timer_list connect_timer; struct work_struct disconnect_worker; /* scan */ struct cfg80211_scan_request *scan_request; struct timer_list scan_timer; /* detect scan timeout */ struct wil_p2p_info p2p; /* keep alive */ struct list_head probe_client_pending; struct mutex probe_client_mutex; /* protect @probe_client_pending */ struct work_struct probe_client_worker; int net_queue_stopped; /* netif_tx_stop_all_queues invoked */ bool fw_stats_ready; /* per-cid statistics are ready inside sta_info */
u64 fw_stats_tsf; /* measurement timestamp */
/* PTK rekey race prevention, this is relevant to station mode only */ enum wil_rekey_state ptk_rekey_state; struct work_struct enable_tx_key_worker;
};
/** * During Rx completion processing, the driver extracts a buffer ID which * is used as an index to the rx_buff_mgmt.buff_arr array and then the SKB * is given to the network stack and the buffer is moved from the 'active' * list to the 'free' list. * During Rx refill, SKBs are attached to free buffers and moved to the * 'active' list.
*/ struct wil_rx_buff_mgmt { struct wil_rx_buff *buff_arr;
size_t size; /* number of items in buff_arr */ struct list_head active; struct list_head free; unsignedlong free_list_empty_cnt; /* statistics */
};
struct wil6210_priv { struct pci_dev *pdev;
u32 bar_size; struct wiphy *wiphy; struct net_device *main_ndev; int n_msi; void __iomem *csr;
DECLARE_BITMAP(status, wil_status_last);
u8 fw_version[ETHTOOL_FWVERS_LEN];
u32 hw_version;
u8 chip_revision; constchar *hw_name; constchar *wil_fw_name; char *board_file;
u32 num_of_brd_entries; struct wil_brd_info *brd_info;
DECLARE_BITMAP(hw_capa, hw_capa_last);
DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX);
DECLARE_BITMAP(platform_capa, WIL_PLATFORM_CAPA_MAX);
u32 recovery_count; /* num of FW recovery attempts in a short time */
u32 recovery_state; /* FW recovery state machine */ unsignedlong last_fw_recovery; /* jiffies of last fw recovery */
wait_queue_head_t wq; /* for all wait_event() use */
u8 max_vifs; /* maximum number of interfaces, including main */ struct wil6210_vif *vifs[WIL_MAX_VIFS]; struct mutex vif_mutex; /* protects access to VIF entries */
atomic_t connected_vifs;
u32 max_assoc_sta; /* max sta's supported by the driver and the FW */
/* register write. wmb() to make sure it is completed */ staticinlinevoid wil_w(struct wil6210_priv *wil, u32 reg, u32 val)
{
writel(val, wil->csr + HOSTADDR(reg));
wmb(); /* wait for write to propagate to the HW */
}
/* WMI for P2P */ int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi); int wmi_start_listen(struct wil6210_vif *vif); int wmi_start_search(struct wil6210_vif *vif); int wmi_stop_discovery(struct wil6210_vif *vif);
int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct cfg80211_mgmt_tx_params *params,
u64 *cookie); void wil_cfg80211_ap_recovery(struct wil6210_priv *wil); int wil_cfg80211_iface_combinations_from_fw( struct wil6210_priv *wil, conststruct wil_fw_record_concurrency *conc); int wil_vif_prepare_stop(struct wil6210_vif *vif);
/* TX API */ int wil_ring_init_tx(struct wil6210_vif *vif, int cid); int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size); int wil_bcast_init(struct wil6210_vif *vif); void wil_bcast_fini(struct wil6210_vif *vif); void wil_bcast_fini_all(struct wil6210_priv *wil);
int wmi_start_sched_scan(struct wil6210_priv *wil, struct cfg80211_sched_scan_request *request); int wmi_stop_sched_scan(struct wil6210_priv *wil); int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len); int wmi_mgmt_tx_ext(struct wil6210_vif *vif, const u8 *buf, size_t len,
u8 channel, u16 duration_ms); int wmi_rbufcap_cfg(struct wil6210_priv *wil, bool enable, u16 threshold);
int wil_wmi2spec_ch(u8 wmi_ch, u8 *spec_ch); int wil_spec2wmi_ch(u8 spec_ch, u8 *wmi_ch); void wil_update_supported_bands(struct wil6210_priv *wil);
int reverse_memcmp(constvoid *cs, constvoid *ct, size_t count);
/* WMI for enhanced DMA */ int wil_wmi_tx_sring_cfg(struct wil6210_priv *wil, int ring_id); int wil_wmi_cfg_def_rx_offload(struct wil6210_priv *wil,
u16 max_rx_pl_per_desc); int wil_wmi_rx_sring_add(struct wil6210_priv *wil, u16 ring_id); int wil_wmi_rx_desc_ring_add(struct wil6210_priv *wil, int status_ring_id); int wil_wmi_tx_desc_ring_add(struct wil6210_vif *vif, int ring_id, int cid, int tid); int wil_wmi_bcast_desc_ring_add(struct wil6210_vif *vif, int ring_id); int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid,
u8 tid, u8 token, u16 status, bool amsdu,
u16 agg_wsize, u16 timeout);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.