1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting
5 * Copyright (c) 2007-2009 Marvell Semiconductor, Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer,
13 *    without modification.
14 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
15 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
16 *    redistribution must be conditioned upon including a substantially
17 *    similar Disclaimer requirement for further binary redistribution.
18 *
19 * NO WARRANTY
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
25 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
28 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGES.
31 *
32 * $FreeBSD: releng/12.0/sys/dev/mwl/if_mwlvar.h 326255 2017-11-27 14:52:40Z pfg $
33 */
34
35/*
36 * Definitions for the Marvell 88W8363 Wireless LAN controller.
37 */
38#ifndef _DEV_MWL_MVVAR_H
39#define _DEV_MWL_MVVAR_H
40
41#include <sys/endian.h>
42#include <sys/bus.h>
43#include <net80211/ieee80211_radiotap.h>
44#include <dev/mwl/mwlhal.h>
45#include <dev/mwl/mwlreg.h>
46#include <dev/mwl/if_mwlioctl.h>
47
48#ifndef MWL_TXBUF
49#define MWL_TXBUF	256		/* number of TX descriptors/buffers */
50#endif
51#ifndef MWL_TXACKBUF
52#define MWL_TXACKBUF	(MWL_TXBUF/2)	/* number of TX ACK desc's/buffers */
53#endif
54#ifndef MWL_RXDESC
55#define MWL_RXDESC	256		/* number of RX descriptors */
56#endif
57#ifndef MWL_RXBUF
58#define MWL_RXBUF	((5*MWL_RXDESC)/2)/* number of RX dma buffers */
59#endif
60#ifndef MWL_MAXBA
61#define	MWL_MAXBA	2		/* max BA streams/sta */
62#endif
63
64#ifdef MWL_SGDMA_SUPPORT
65#define	MWL_TXDESC	6		/* max tx descriptors/segments */
66#else
67#define	MWL_TXDESC	1		/* max tx descriptors/segments */
68#endif
69#ifndef MWL_AGGR_SIZE
70#define	MWL_AGGR_SIZE	3839		/* max tx aggregation size */
71#endif
72#define	MWL_AGEINTERVAL	1		/* poke f/w every sec to age q's */
73#define	MWL_MAXSTAID	64		/* max of 64 stations */
74
75/*
76 * DMA state for tx/rx descriptors.
77 */
78
79/*
80 * Software backed version of tx/rx descriptors.  We keep
81 * the software state out of the h/w descriptor structure
82 * so that may be allocated in uncached memory w/o paying
83 * performance hit.
84 */
85struct mwl_txbuf {
86	STAILQ_ENTRY(mwl_txbuf) bf_list;
87	void 		*bf_desc;	/* h/w descriptor */
88	bus_addr_t	bf_daddr;	/* physical addr of desc */
89	bus_dmamap_t	bf_dmamap;	/* DMA map for descriptors */
90	int		bf_nseg;
91	bus_dma_segment_t bf_segs[MWL_TXDESC];
92	struct mbuf	*bf_m;
93	struct ieee80211_node *bf_node;
94	struct mwl_txq	*bf_txq;		/* backpointer to tx q/ring */
95};
96typedef STAILQ_HEAD(, mwl_txbuf) mwl_txbufhead;
97
98/*
99 * Common "base class" for tx/rx descriptor resources
100 * allocated using the bus dma api.
101 */
102struct mwl_descdma {
103	const char*		dd_name;
104	void			*dd_desc;	/* descriptors */
105	bus_addr_t		dd_desc_paddr;	/* physical addr of dd_desc */
106	bus_size_t		dd_desc_len;	/* size of dd_desc */
107	bus_dma_segment_t	dd_dseg;
108	int			dd_dnseg;	/* number of segments */
109	bus_dma_tag_t		dd_dmat;	/* bus DMA tag */
110	bus_dmamap_t		dd_dmamap;	/* DMA map for descriptors */
111	void			*dd_bufptr;	/* associated buffers */
112};
113
114/*
115 * TX/RX ring definitions.  There are 4 tx rings, one
116 * per AC, and 1 rx ring.  Note carefully that transmit
117 * descriptors are treated as a contiguous chunk and the
118 * firmware pre-fetches descriptors.  This means that we
119 * must preserve order when moving descriptors between
120 * the active+free lists; otherwise we may stall transmit.
121 */
122struct mwl_txq {
123	struct mwl_descdma dma;		/* bus dma resources */
124	struct mtx	lock;		/* tx q lock */
125	char		name[12];	/* e.g. "mwl0_txq4" */
126	int		qnum;		/* f/w q number */
127	int		txpri;		/* f/w tx priority */
128	int		nfree;		/* # buffers on free list */
129	mwl_txbufhead	free;		/* queue of free buffers */
130	mwl_txbufhead	active;		/* queue of active buffers */
131};
132
133#define	MWL_TXQ_LOCK_INIT(_sc, _tq) do { \
134	snprintf((_tq)->name, sizeof((_tq)->name), "%s_txq%u", \
135		device_get_nameunit((_sc)->sc_dev), (_tq)->qnum); \
136	mtx_init(&(_tq)->lock, (_tq)->name, NULL, MTX_DEF); \
137} while (0)
138#define	MWL_TXQ_LOCK_DESTROY(_tq)	mtx_destroy(&(_tq)->lock)
139#define	MWL_TXQ_LOCK(_tq)		mtx_lock(&(_tq)->lock)
140#define	MWL_TXQ_UNLOCK(_tq)		mtx_unlock(&(_tq)->lock)
141#define	MWL_TXQ_LOCK_ASSERT(_tq)	mtx_assert(&(_tq)->lock, MA_OWNED)
142
143#define	MWL_TXDESC_SYNC(txq, ds, how) do { \
144	bus_dmamap_sync((txq)->dma.dd_dmat, (txq)->dma.dd_dmamap, how); \
145} while(0)
146
147/*
148 * RX dma buffers that are not in use are kept on a list.
149 */
150struct mwl_jumbo {
151	SLIST_ENTRY(mwl_jumbo) next;
152};
153typedef SLIST_HEAD(, mwl_jumbo) mwl_jumbohead;
154
155#define	MWL_JUMBO_DATA2BUF(_data)	((struct mwl_jumbo *)(_data))
156#define	MWL_JUMBO_BUF2DATA(_buf)		((uint8_t *)(_buf))
157#define	MWL_JUMBO_OFFSET(_sc, _data) \
158	(((const uint8_t *)(_data)) - (const uint8_t *)((_sc)->sc_rxmem))
159#define	MWL_JUMBO_DMA_ADDR(_sc, _data) \
160	((_sc)->sc_rxmem_paddr + MWL_JUMBO_OFFSET(_sc, _data))
161
162struct mwl_rxbuf {
163	STAILQ_ENTRY(mwl_rxbuf) bf_list;
164	void 		*bf_desc;	/* h/w descriptor */
165	bus_addr_t	bf_daddr;	/* physical addr of desc */
166	uint8_t		*bf_data;	/* rx data area */
167};
168typedef STAILQ_HEAD(, mwl_rxbuf) mwl_rxbufhead;
169
170#define	MWL_RXDESC_SYNC(sc, ds, how) do { \
171	bus_dmamap_sync((sc)->sc_rxdma.dd_dmat, (sc)->sc_rxdma.dd_dmamap, how);\
172} while (0)
173
174/*
175 * BA stream state.  One of these is setup for each stream
176 * allocated/created for use.  We pre-allocate the h/w stream
177 * before sending ADDBA request then complete the setup when
178 * get ADDBA response (success).  The completed state is setup
179 * to optimize the fast path in mwl_txstart--we precalculate
180 * the QoS control bits in the outbound frame and use those
181 * to identify which BA stream to use (assigning the h/w q to
182 * the TxPriority field of the descriptor).
183 *
184 * NB: Each station may have at most MWL_MAXBA streams at one time.
185 */
186struct mwl_bastate {
187	uint16_t	qos;		/* QoS ctl for BA stream */
188	uint8_t		txq;		/* h/w q for BA stream */
189	const MWL_HAL_BASTREAM *bastream; /* A-MPDU BA stream */
190};
191
192static __inline__ void
193mwl_bastream_setup(struct mwl_bastate *bas, int tid, int txq)
194{
195	bas->txq = txq;
196	bas->qos = htole16(tid | IEEE80211_QOS_ACKPOLICY_BA);
197}
198
199static __inline__ void
200mwl_bastream_free(struct mwl_bastate *bas)
201{
202	bas->qos = 0;
203	bas->bastream = NULL;
204	/* NB: don't need to clear txq */
205}
206
207/*
208 * Check the QoS control bits from an outbound frame against the
209 * value calculated when a BA stream is setup (above).  We need
210 * to match the TID and also the ACK policy so we only match AMPDU
211 * frames.  The bits from the frame are assumed in network byte
212 * order, hence the potential byte swap.
213 */
214static __inline__ int
215mwl_bastream_match(const struct mwl_bastate *bas, uint16_t qos)
216{
217	return (qos & htole16(IEEE80211_QOS_TID|IEEE80211_QOS_ACKPOLICY)) ==
218	    bas->qos;
219}
220
221/* driver-specific node state */
222struct mwl_node {
223	struct ieee80211_node mn_node;	/* base class */
224	struct mwl_ant_info mn_ai;	/* antenna info */
225	uint32_t	mn_avgrssi;	/* average rssi over all rx frames */
226	uint16_t	mn_staid;	/* firmware station id */
227	struct mwl_bastate mn_ba[MWL_MAXBA];
228	struct mwl_hal_vap *mn_hvap;	/* hal vap handle */
229};
230#define	MWL_NODE(ni)		((struct mwl_node *)(ni))
231#define	MWL_NODE_CONST(ni)	((const struct mwl_node *)(ni))
232
233/*
234 * Driver-specific vap state.
235 */
236struct mwl_vap {
237	struct ieee80211vap mv_vap;		/* base class */
238	struct mwl_hal_vap *mv_hvap;		/* hal vap handle */
239	struct mwl_hal_vap *mv_ap_hvap;		/* ap hal vap handle for wds */
240	uint16_t	mv_last_ps_sta;		/* last count of ps sta's */
241	uint16_t	mv_eapolformat;		/* fixed tx rate for EAPOL */
242	int		(*mv_newstate)(struct ieee80211vap *,
243				    enum ieee80211_state, int);
244	int		(*mv_set_tim)(struct ieee80211_node *, int);
245};
246#define	MWL_VAP(vap)	((struct mwl_vap *)(vap))
247#define	MWL_VAP_CONST(vap)	((const struct mwl_vap *)(vap))
248
249struct mwl_softc {
250	struct ieee80211com	sc_ic;
251	struct mbufq		sc_snd;
252	struct mwl_stats	sc_stats;	/* interface statistics */
253	int			sc_debug;
254	device_t		sc_dev;
255	bus_dma_tag_t		sc_dmat;	/* bus DMA tag */
256	bus_space_handle_t	sc_io0h;	/* BAR 0 */
257	bus_space_tag_t		sc_io0t;
258	bus_space_handle_t	sc_io1h;	/* BAR 1 */
259	bus_space_tag_t		sc_io1t;
260	struct mtx		sc_mtx;		/* master lock (recursive) */
261	struct taskqueue	*sc_tq;		/* private task queue */
262	struct callout	sc_watchdog;
263	int			sc_tx_timer;
264	unsigned int		sc_running : 1,
265				sc_invalid : 1,	/* disable hardware accesses */
266				sc_recvsetup:1,	/* recv setup */
267				sc_csapending:1,/* 11h channel switch pending */
268				sc_radarena : 1,/* radar detection enabled */
269				sc_rxblocked: 1;/* rx waiting for dma buffers */
270
271	struct mwl_hal		*sc_mh;		/* h/w access layer */
272	struct mwl_hal_vap	*sc_hvap;	/* hal vap handle */
273	struct mwl_hal_hwspec	sc_hwspecs;	/* h/w capabilities */
274	uint32_t		sc_fwrelease;	/* release # of loaded f/w */
275	struct mwl_hal_txrxdma	sc_hwdma;	/* h/w dma setup */
276	uint32_t		sc_imask;	/* interrupt mask copy */
277	enum ieee80211_phymode	sc_curmode;
278	u_int16_t		sc_curaid;	/* current association id */
279	u_int8_t		sc_curbssid[IEEE80211_ADDR_LEN];
280	MWL_HAL_CHANNEL		sc_curchan;
281	MWL_HAL_TXRATE_HANDLING	sc_txratehandling;
282	u_int16_t		sc_rxantenna;	/* rx antenna */
283	u_int16_t		sc_txantenna;	/* tx antenna */
284	uint8_t			sc_napvaps;	/* # ap mode vaps */
285	uint8_t			sc_nwdsvaps;	/* # wds mode vaps */
286	uint8_t			sc_nstavaps;	/* # sta mode vaps */
287	uint8_t			sc_ndwdsvaps;	/* # sta mode dwds vaps */
288	uint8_t			sc_nbssid0;	/* # vap's using base mac */
289	uint32_t		sc_bssidmask;	/* bssid mask */
290
291	void			(*sc_recv_mgmt)(struct ieee80211com *,
292				    struct mbuf *,
293				    struct ieee80211_node *,
294				    int, int, int, u_int32_t);
295	int			(*sc_newstate)(struct ieee80211com *,
296				    enum ieee80211_state, int);
297	void 			(*sc_node_cleanup)(struct ieee80211_node *);
298	void 			(*sc_node_drain)(struct ieee80211_node *);
299	int			(*sc_recv_action)(struct ieee80211_node *,
300				    const struct ieee80211_frame *,
301				    const uint8_t *, const uint8_t *);
302	int			(*sc_addba_request)(struct ieee80211_node *,
303				    struct ieee80211_tx_ampdu *,
304				    int dialogtoken, int baparamset,
305				    int batimeout);
306	int			(*sc_addba_response)(struct ieee80211_node *,
307				    struct ieee80211_tx_ampdu *,
308				    int status, int baparamset,
309				    int batimeout);
310	void			(*sc_addba_stop)(struct ieee80211_node *,
311				    struct ieee80211_tx_ampdu *);
312
313	struct mwl_descdma	sc_rxdma;	/* rx bus dma resources */
314	mwl_rxbufhead		sc_rxbuf;	/* rx buffers */
315	struct mwl_rxbuf	*sc_rxnext;	/* next rx buffer to process */
316	struct task		sc_rxtask;	/* rx int processing */
317	void			*sc_rxmem;	/* rx dma buffer pool */
318	bus_dma_tag_t		sc_rxdmat;	/* rx bus DMA tag */
319	bus_size_t		sc_rxmemsize;	/* rx dma buffer pool size */
320	bus_dmamap_t		sc_rxmap;	/* map for rx dma buffers */
321	bus_addr_t		sc_rxmem_paddr;	/* physical addr of sc_rxmem */
322	mwl_jumbohead		sc_rxfree;	/* list of free dma buffers */
323	int			sc_nrxfree;	/* # buffers on rx free list */
324	struct mtx		sc_rxlock;	/* lock on sc_rxfree */
325
326	struct mwl_txq		sc_txq[MWL_NUM_TX_QUEUES];
327	struct mwl_txq		*sc_ac2q[5];	/* WME AC -> h/w q map */
328	struct mbuf		*sc_aggrq;	/* aggregation q */
329	struct task		sc_txtask;	/* tx int processing */
330	struct task		sc_bawatchdogtask;/* BA watchdog processing */
331
332	struct task		sc_radartask;	/* radar detect processing */
333	struct task		sc_chanswitchtask;/* chan switch processing */
334
335	uint8_t			sc_staid[MWL_MAXSTAID/NBBY];
336	int			sc_ageinterval;
337	struct callout		sc_timer;	/* periodic work */
338
339	struct mwl_tx_radiotap_header sc_tx_th;
340	struct mwl_rx_radiotap_header sc_rx_th;
341
342#if defined(__HAIKU__)
343	uint32_t sc_intr_status;
344#endif
345};
346
347#define	MWL_LOCK_INIT(_sc) \
348	mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
349		 NULL, MTX_DEF | MTX_RECURSE)
350#define	MWL_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx)
351#define	MWL_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
352#define	MWL_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
353#define	MWL_LOCK_ASSERT(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
354
355#define	MWL_RXFREE_INIT(_sc) \
356	mtx_init(&(_sc)->sc_rxlock, device_get_nameunit((_sc)->sc_dev), \
357		 NULL, MTX_DEF)
358#define	MWL_RXFREE_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_rxlock)
359#define	MWL_RXFREE_LOCK(_sc)	mtx_lock(&(_sc)->sc_rxlock)
360#define	MWL_RXFREE_UNLOCK(_sc)	mtx_unlock(&(_sc)->sc_rxlock)
361#define	MWL_RXFREE_ASSERT(_sc)	mtx_assert(&(_sc)->sc_rxlock, MA_OWNED)
362
363int	mwl_attach(u_int16_t, struct mwl_softc *);
364int	mwl_detach(struct mwl_softc *);
365void	mwl_resume(struct mwl_softc *);
366void	mwl_suspend(struct mwl_softc *);
367void	mwl_shutdown(void *);
368void	mwl_intr(void *);
369
370#endif /* _DEV_MWL_MVVAR_H */
371