if_mwlvar.h revision 195171
1193240Ssam/*- 2193240Ssam * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting 3193240Ssam * Copyright (c) 2007-2009 Marvell Semiconductor, Inc. 4193240Ssam * All rights reserved. 5193240Ssam * 6193240Ssam * Redistribution and use in source and binary forms, with or without 7193240Ssam * modification, are permitted provided that the following conditions 8193240Ssam * are met: 9193240Ssam * 1. Redistributions of source code must retain the above copyright 10193240Ssam * notice, this list of conditions and the following disclaimer, 11193240Ssam * without modification. 12193240Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer 13193240Ssam * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 14193240Ssam * redistribution must be conditioned upon including a substantially 15193240Ssam * similar Disclaimer requirement for further binary redistribution. 16193240Ssam * 17193240Ssam * NO WARRANTY 18193240Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19193240Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20193240Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 21193240Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22193240Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 23193240Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24193240Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25193240Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26193240Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27193240Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28193240Ssam * THE POSSIBILITY OF SUCH DAMAGES. 29193240Ssam * 30193240Ssam * $FreeBSD: head/sys/dev/mwl/if_mwlvar.h 195171 2009-06-29 18:42:54Z sam $ 31193240Ssam */ 32193240Ssam 33193240Ssam/* 34193240Ssam * Definitions for the Marvell 88W8363 Wireless LAN controller. 35193240Ssam */ 36193240Ssam#ifndef _DEV_MWL_MVVAR_H 37193240Ssam#define _DEV_MWL_MVVAR_H 38193240Ssam 39193240Ssam#include <sys/endian.h> 40193240Ssam#include <net80211/ieee80211_radiotap.h> 41193240Ssam#include <dev/mwl/mwlhal.h> 42193240Ssam#include <dev/mwl/mwlreg.h> 43193240Ssam#include <dev/mwl/if_mwlioctl.h> 44193240Ssam 45193240Ssam#ifndef MWL_TXBUF 46193240Ssam#define MWL_TXBUF 256 /* number of TX descriptors/buffers */ 47193240Ssam#endif 48195171Ssam#ifndef MWL_TXACKBUF 49195171Ssam#define MWL_TXACKBUF (MWL_TXBUF/2) /* number of TX ACK desc's/buffers */ 50195171Ssam#endif 51193240Ssam#ifndef MWL_RXDESC 52193240Ssam#define MWL_RXDESC 256 /* number of RX descriptors */ 53193240Ssam#endif 54193240Ssam#ifndef MWL_RXBUF 55193240Ssam#define MWL_RXBUF ((5*MWL_RXDESC)/2)/* number of RX dma buffers */ 56193240Ssam#endif 57193240Ssam#ifndef MWL_MAXBA 58193240Ssam#define MWL_MAXBA 2 /* max BA streams/sta */ 59193240Ssam#endif 60193240Ssam 61193240Ssam#ifdef MWL_SGDMA_SUPPORT 62193240Ssam#define MWL_TXDESC 6 /* max tx descriptors/segments */ 63193240Ssam#else 64193240Ssam#define MWL_TXDESC 1 /* max tx descriptors/segments */ 65193240Ssam#endif 66193240Ssam#ifndef MWL_AGGR_SIZE 67193240Ssam#define MWL_AGGR_SIZE 3839 /* max tx agregation size */ 68193240Ssam#endif 69193240Ssam#define MWL_AGEINTERVAL 1 /* poke f/w every sec to age q's */ 70193240Ssam#define MWL_MAXSTAID 64 /* max of 64 stations */ 71193240Ssam 72193240Ssam/* 73193240Ssam * DMA state for tx/rx descriptors. 74193240Ssam */ 75193240Ssam 76193240Ssam/* 77193240Ssam * Software backed version of tx/rx descriptors. We keep 78193240Ssam * the software state out of the h/w descriptor structure 79193240Ssam * so that may be allocated in uncached memory w/o paying 80193240Ssam * performance hit. 81193240Ssam */ 82193240Ssamstruct mwl_txbuf { 83193240Ssam STAILQ_ENTRY(mwl_txbuf) bf_list; 84193240Ssam void *bf_desc; /* h/w descriptor */ 85193240Ssam bus_addr_t bf_daddr; /* physical addr of desc */ 86193240Ssam bus_dmamap_t bf_dmamap; /* DMA map for descriptors */ 87193240Ssam int bf_nseg; 88193240Ssam bus_dma_segment_t bf_segs[MWL_TXDESC]; 89193240Ssam struct mbuf *bf_m; 90193240Ssam struct ieee80211_node *bf_node; 91193240Ssam struct mwl_txq *bf_txq; /* backpointer to tx q/ring */ 92193240Ssam}; 93193240Ssamtypedef STAILQ_HEAD(, mwl_txbuf) mwl_txbufhead; 94193240Ssam 95193240Ssam/* 96193240Ssam * Common "base class" for tx/rx descriptor resources 97193240Ssam * allocated using the bus dma api. 98193240Ssam */ 99193240Ssamstruct mwl_descdma { 100193240Ssam const char* dd_name; 101193240Ssam void *dd_desc; /* descriptors */ 102193240Ssam bus_addr_t dd_desc_paddr; /* physical addr of dd_desc */ 103193240Ssam bus_size_t dd_desc_len; /* size of dd_desc */ 104193240Ssam bus_dma_segment_t dd_dseg; 105193240Ssam int dd_dnseg; /* number of segments */ 106193240Ssam bus_dma_tag_t dd_dmat; /* bus DMA tag */ 107193240Ssam bus_dmamap_t dd_dmamap; /* DMA map for descriptors */ 108193240Ssam void *dd_bufptr; /* associated buffers */ 109193240Ssam}; 110193240Ssam 111193240Ssam/* 112193240Ssam * TX/RX ring definitions. There are 4 tx rings, one 113193240Ssam * per AC, and 1 rx ring. Note carefully that transmit 114193240Ssam * descriptors are treated as a contiguous chunk and the 115193240Ssam * firmware pre-fetches descriptors. This means that we 116193240Ssam * must preserve order when moving descriptors between 117193240Ssam * the active+free lists; otherwise we may stall transmit. 118193240Ssam */ 119193240Ssamstruct mwl_txq { 120193240Ssam struct mwl_descdma dma; /* bus dma resources */ 121193240Ssam struct mtx lock; /* tx q lock */ 122193240Ssam char name[12]; /* e.g. "mwl0_txq4" */ 123193240Ssam int qnum; /* f/w q number */ 124193240Ssam int txpri; /* f/w tx priority */ 125193240Ssam int nfree; /* # buffers on free list */ 126193240Ssam mwl_txbufhead free; /* queue of free buffers */ 127193240Ssam mwl_txbufhead active; /* queue of active buffers */ 128193240Ssam}; 129193240Ssam 130193240Ssam#define MWL_TXQ_LOCK_INIT(_sc, _tq) do { \ 131193240Ssam snprintf((_tq)->name, sizeof((_tq)->name), "%s_txq%u", \ 132193240Ssam device_get_nameunit((_sc)->sc_dev), (_tq)->qnum); \ 133193240Ssam mtx_init(&(_tq)->lock, (_tq)->name, NULL, MTX_DEF); \ 134193240Ssam} while (0) 135193240Ssam#define MWL_TXQ_LOCK_DESTROY(_tq) mtx_destroy(&(_tq)->lock) 136193240Ssam#define MWL_TXQ_LOCK(_tq) mtx_lock(&(_tq)->lock) 137193240Ssam#define MWL_TXQ_UNLOCK(_tq) mtx_unlock(&(_tq)->lock) 138193240Ssam#define MWL_TXQ_LOCK_ASSERT(_tq) mtx_assert(&(_tq)->lock, MA_OWNED) 139193240Ssam 140193240Ssam#define MWL_TXDESC_SYNC(txq, ds, how) do { \ 141193240Ssam bus_dmamap_sync((txq)->dma.dd_dmat, (txq)->dma.dd_dmamap, how); \ 142193240Ssam} while(0) 143193240Ssam 144193240Ssam/* 145193240Ssam * RX dma buffers that are not in use are kept on a list. 146193240Ssam */ 147193240Ssamstruct mwl_jumbo { 148193240Ssam SLIST_ENTRY(mwl_jumbo) next; 149193240Ssam}; 150193240Ssamtypedef SLIST_HEAD(, mwl_jumbo) mwl_jumbohead; 151193240Ssam 152193240Ssam#define MWL_JUMBO_DATA2BUF(_data) ((struct mwl_jumbo *)(_data)) 153193240Ssam#define MWL_JUMBO_BUF2DATA(_buf) ((uint8_t *)(_buf)) 154193240Ssam#define MWL_JUMBO_OFFSET(_sc, _data) \ 155193240Ssam (((const uint8_t *)(_data)) - (const uint8_t *)((_sc)->sc_rxmem)) 156193240Ssam#define MWL_JUMBO_DMA_ADDR(_sc, _data) \ 157193240Ssam ((_sc)->sc_rxmem_paddr + MWL_JUMBO_OFFSET(_sc, _data)) 158193240Ssam 159193240Ssamstruct mwl_rxbuf { 160193240Ssam STAILQ_ENTRY(mwl_rxbuf) bf_list; 161193240Ssam void *bf_desc; /* h/w descriptor */ 162193240Ssam bus_addr_t bf_daddr; /* physical addr of desc */ 163193240Ssam uint8_t *bf_data; /* rx data area */ 164193240Ssam}; 165193240Ssamtypedef STAILQ_HEAD(, mwl_rxbuf) mwl_rxbufhead; 166193240Ssam 167193240Ssam#define MWL_RXDESC_SYNC(sc, ds, how) do { \ 168193240Ssam bus_dmamap_sync((sc)->sc_rxdma.dd_dmat, (sc)->sc_rxdma.dd_dmamap, how);\ 169193240Ssam} while (0) 170193240Ssam 171193240Ssam/* 172193240Ssam * BA stream state. One of these is setup for each stream 173193240Ssam * allocated/created for use. We pre-allocate the h/w stream 174193240Ssam * before sending ADDBA request then complete the setup when 175193240Ssam * get ADDBA response (success). The completed state is setup 176193240Ssam * to optimize the fast path in mwl_txstart--we precalculate 177193240Ssam * the QoS control bits in the outbound frame and use those 178193240Ssam * to identify which BA stream to use (assigning the h/w q to 179193240Ssam * the TxPriority field of the descriptor). 180193240Ssam * 181193240Ssam * NB: Each station may have at most MWL_MAXBA streams at one time. 182193240Ssam */ 183193240Ssamstruct mwl_bastate { 184193240Ssam uint16_t qos; /* QoS ctl for BA stream */ 185193240Ssam uint8_t txq; /* h/w q for BA stream */ 186193240Ssam const MWL_HAL_BASTREAM *bastream; /* A-MPDU BA stream */ 187193240Ssam}; 188193240Ssam 189193240Ssamstatic __inline__ void 190193240Ssammwl_bastream_setup(struct mwl_bastate *bas, int ac, int txq) 191193240Ssam{ 192193240Ssam bas->txq = txq; 193193240Ssam bas->qos = htole16(WME_AC_TO_TID(ac) | IEEE80211_QOS_ACKPOLICY_BA); 194193240Ssam} 195193240Ssam 196193240Ssamstatic __inline__ void 197193240Ssammwl_bastream_free(struct mwl_bastate *bas) 198193240Ssam{ 199193240Ssam bas->qos = 0; 200193240Ssam bas->bastream = NULL; 201193240Ssam /* NB: don't need to clear txq */ 202193240Ssam} 203193240Ssam 204193240Ssam/* 205193240Ssam * Check the QoS control bits from an outbound frame against the 206193240Ssam * value calculated when a BA stream is setup (above). We need 207193240Ssam * to match the TID and also the ACK policy so we only match AMPDU 208193240Ssam * frames. The bits from the frame are assumed in network byte 209193240Ssam * order, hence the potential byte swap. 210193240Ssam */ 211193240Ssamstatic __inline__ int 212193240Ssammwl_bastream_match(const struct mwl_bastate *bas, uint16_t qos) 213193240Ssam{ 214193240Ssam return (qos & htole16(IEEE80211_QOS_TID|IEEE80211_QOS_ACKPOLICY)) == 215193240Ssam bas->qos; 216193240Ssam} 217193240Ssam 218193240Ssam/* driver-specific node state */ 219193240Ssamstruct mwl_node { 220193240Ssam struct ieee80211_node mn_node; /* base class */ 221193240Ssam struct mwl_ant_info mn_ai; /* antenna info */ 222193240Ssam uint32_t mn_avgrssi; /* average rssi over all rx frames */ 223193240Ssam uint16_t mn_staid; /* firmware station id */ 224193240Ssam struct mwl_bastate mn_ba[MWL_MAXBA]; 225193240Ssam struct mwl_hal_vap *mn_hvap; /* hal vap handle */ 226193240Ssam}; 227193240Ssam#define MWL_NODE(ni) ((struct mwl_node *)(ni)) 228193240Ssam#define MWL_NODE_CONST(ni) ((const struct mwl_node *)(ni)) 229193240Ssam 230193240Ssam/* 231193240Ssam * Driver-specific vap state. 232193240Ssam */ 233193240Ssamstruct mwl_vap { 234193240Ssam struct ieee80211vap mv_vap; /* base class */ 235193240Ssam struct mwl_hal_vap *mv_hvap; /* hal vap handle */ 236193240Ssam struct mwl_hal_vap *mv_ap_hvap; /* ap hal vap handle for wds */ 237193240Ssam uint16_t mv_last_ps_sta; /* last count of ps sta's */ 238193240Ssam uint16_t mv_eapolformat; /* fixed tx rate for EAPOL */ 239193240Ssam int (*mv_newstate)(struct ieee80211vap *, 240193240Ssam enum ieee80211_state, int); 241193240Ssam int (*mv_set_tim)(struct ieee80211_node *, int); 242193240Ssam}; 243193240Ssam#define MWL_VAP(vap) ((struct mwl_vap *)(vap)) 244193240Ssam#define MWL_VAP_CONST(vap) ((const struct mwl_vap *)(vap)) 245193240Ssam 246193240Ssamstruct mwl_softc { 247193240Ssam struct ifnet *sc_ifp; /* interface common */ 248193240Ssam struct mwl_stats sc_stats; /* interface statistics */ 249193240Ssam int sc_debug; 250193240Ssam device_t sc_dev; 251193240Ssam bus_dma_tag_t sc_dmat; /* bus DMA tag */ 252193240Ssam bus_space_handle_t sc_io0h; /* BAR 0 */ 253193240Ssam bus_space_tag_t sc_io0t; 254193240Ssam bus_space_handle_t sc_io1h; /* BAR 1 */ 255193240Ssam bus_space_tag_t sc_io1t; 256193240Ssam struct mtx sc_mtx; /* master lock (recursive) */ 257193240Ssam struct taskqueue *sc_tq; /* private task queue */ 258193240Ssam unsigned int sc_invalid : 1, /* disable hardware accesses */ 259193240Ssam sc_recvsetup:1, /* recv setup */ 260193240Ssam sc_csapending:1,/* 11h channel switch pending */ 261193240Ssam sc_radarena : 1,/* radar detection enabled */ 262193240Ssam sc_rxblocked: 1;/* rx waiting for dma buffers */ 263193240Ssam 264193240Ssam struct mwl_hal *sc_mh; /* h/w access layer */ 265193240Ssam struct mwl_hal_vap *sc_hvap; /* hal vap handle */ 266193240Ssam struct mwl_hal_hwspec sc_hwspecs; /* h/w capabilities */ 267193240Ssam uint32_t sc_fwrelease; /* release # of loaded f/w */ 268193240Ssam struct mwl_hal_txrxdma sc_hwdma; /* h/w dma setup */ 269193240Ssam uint32_t sc_imask; /* interrupt mask copy */ 270193240Ssam enum ieee80211_phymode sc_curmode; 271193240Ssam u_int16_t sc_curaid; /* current association id */ 272193240Ssam u_int8_t sc_curbssid[IEEE80211_ADDR_LEN]; 273193240Ssam MWL_HAL_CHANNEL sc_curchan; 274193240Ssam MWL_HAL_TXRATE_HANDLING sc_txratehandling; 275193240Ssam u_int16_t sc_rxantenna; /* rx antenna */ 276193240Ssam u_int16_t sc_txantenna; /* tx antenna */ 277193240Ssam uint8_t sc_napvaps; /* # ap mode vaps */ 278193240Ssam uint8_t sc_nwdsvaps; /* # wds mode vaps */ 279193240Ssam uint8_t sc_nstavaps; /* # sta mode vaps */ 280195171Ssam uint8_t sc_ndwdsvaps; /* # sta mode dwds vaps */ 281193240Ssam uint8_t sc_nbssid0; /* # vap's using base mac */ 282193240Ssam uint32_t sc_bssidmask; /* bssid mask */ 283193240Ssam 284193240Ssam void (*sc_recv_mgmt)(struct ieee80211com *, 285193240Ssam struct mbuf *, 286193240Ssam struct ieee80211_node *, 287193240Ssam int, int, int, u_int32_t); 288193240Ssam int (*sc_newstate)(struct ieee80211com *, 289193240Ssam enum ieee80211_state, int); 290193240Ssam void (*sc_node_cleanup)(struct ieee80211_node *); 291193240Ssam void (*sc_node_drain)(struct ieee80211_node *); 292193240Ssam void (*sc_recv_action)(struct ieee80211_node *, 293193240Ssam const uint8_t *, const uint8_t *); 294193240Ssam int (*sc_addba_request)(struct ieee80211_node *, 295193240Ssam struct ieee80211_tx_ampdu *, 296193240Ssam int dialogtoken, int baparamset, 297193240Ssam int batimeout); 298193240Ssam int (*sc_addba_response)(struct ieee80211_node *, 299193240Ssam struct ieee80211_tx_ampdu *, 300193240Ssam int status, int baparamset, 301193240Ssam int batimeout); 302193240Ssam void (*sc_addba_stop)(struct ieee80211_node *, 303193240Ssam struct ieee80211_tx_ampdu *); 304193240Ssam 305193240Ssam struct mwl_descdma sc_rxdma; /* rx bus dma resources */ 306193240Ssam mwl_rxbufhead sc_rxbuf; /* rx buffers */ 307193240Ssam struct mwl_rxbuf *sc_rxnext; /* next rx buffer to process */ 308193240Ssam struct task sc_rxtask; /* rx int processing */ 309193240Ssam void *sc_rxmem; /* rx dma buffer pool */ 310193240Ssam bus_dma_tag_t sc_rxdmat; /* rx bus DMA tag */ 311193240Ssam bus_size_t sc_rxmemsize; /* rx dma buffer pool size */ 312193240Ssam bus_dmamap_t sc_rxmap; /* map for rx dma buffers */ 313193240Ssam bus_addr_t sc_rxmem_paddr; /* physical addr of sc_rxmem */ 314193240Ssam mwl_jumbohead sc_rxfree; /* list of free dma buffers */ 315193240Ssam int sc_nrxfree; /* # buffers on rx free list */ 316193240Ssam struct mtx sc_rxlock; /* lock on sc_rxfree */ 317193240Ssam 318193240Ssam struct mwl_txq sc_txq[MWL_NUM_TX_QUEUES]; 319193240Ssam struct mwl_txq *sc_ac2q[5]; /* WME AC -> h/w q map */ 320193240Ssam struct mbuf *sc_aggrq; /* aggregation q */ 321193240Ssam struct task sc_txtask; /* tx int processing */ 322193240Ssam struct task sc_bawatchdogtask;/* BA watchdog processing */ 323193240Ssam 324193240Ssam struct task sc_radartask; /* radar detect processing */ 325193240Ssam struct task sc_chanswitchtask;/* chan switch processing */ 326193240Ssam 327193240Ssam uint8_t sc_staid[MWL_MAXSTAID/NBBY]; 328193240Ssam int sc_ageinterval; 329193240Ssam struct callout sc_timer; /* periodic work */ 330193240Ssam 331193240Ssam struct mwl_tx_radiotap_header sc_tx_th; 332193240Ssam struct mwl_rx_radiotap_header sc_rx_th; 333193240Ssam}; 334193240Ssam 335193240Ssam#define MWL_LOCK_INIT(_sc) \ 336193240Ssam mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ 337193240Ssam NULL, MTX_DEF | MTX_RECURSE) 338193240Ssam#define MWL_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) 339193240Ssam#define MWL_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 340193240Ssam#define MWL_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 341193240Ssam#define MWL_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) 342193240Ssam 343193240Ssam#define MWL_RXFREE_INIT(_sc) \ 344193240Ssam mtx_init(&(_sc)->sc_rxlock, device_get_nameunit((_sc)->sc_dev), \ 345193240Ssam NULL, MTX_DEF) 346193240Ssam#define MWL_RXFREE_DESTROY(_sc) mtx_destroy(&(_sc)->sc_rxlock) 347193240Ssam#define MWL_RXFREE_LOCK(_sc) mtx_lock(&(_sc)->sc_rxlock) 348193240Ssam#define MWL_RXFREE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_rxlock) 349193240Ssam#define MWL_RXFREE_ASSERT(_sc) mtx_assert(&(_sc)->sc_rxlock, MA_OWNED) 350193240Ssam 351193240Ssamint mwl_attach(u_int16_t, struct mwl_softc *); 352193240Ssamint mwl_detach(struct mwl_softc *); 353193240Ssamvoid mwl_resume(struct mwl_softc *); 354193240Ssamvoid mwl_suspend(struct mwl_softc *); 355193240Ssamvoid mwl_shutdown(void *); 356193240Ssamvoid mwl_intr(void *); 357193240Ssam 358193240Ssam#endif /* _DEV_MWL_MVVAR_H */ 359