Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/mwl/if_mwl.c
Show First 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | |||||
#ifdef INET | #ifdef INET | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/if_ether.h> | #include <netinet/if_ether.h> | ||||
#endif /* INET */ | #endif /* INET */ | ||||
#include <dev/mwl/if_mwlvar.h> | #include <dev/mwl/if_mwlvar.h> | ||||
#include <dev/mwl/mwldiag.h> | #include <dev/mwl/mwldiag.h> | ||||
/* idiomatic shorthands: MS = mask+shift, SM = shift+mask */ | |||||
#define MS(v,x) (((v) & x) >> x##_S) | |||||
#define SM(v,x) (((v) << x##_S) & x) | |||||
static struct ieee80211vap *mwl_vap_create(struct ieee80211com *, | static struct ieee80211vap *mwl_vap_create(struct ieee80211com *, | ||||
const char [IFNAMSIZ], int, enum ieee80211_opmode, int, | const char [IFNAMSIZ], int, enum ieee80211_opmode, int, | ||||
const uint8_t [IEEE80211_ADDR_LEN], | const uint8_t [IEEE80211_ADDR_LEN], | ||||
const uint8_t [IEEE80211_ADDR_LEN]); | const uint8_t [IEEE80211_ADDR_LEN]); | ||||
static void mwl_vap_delete(struct ieee80211vap *); | static void mwl_vap_delete(struct ieee80211vap *); | ||||
static int mwl_setupdma(struct mwl_softc *); | static int mwl_setupdma(struct mwl_softc *); | ||||
static int mwl_hal_reset(struct mwl_softc *sc); | static int mwl_hal_reset(struct mwl_softc *sc); | ||||
static int mwl_init(struct mwl_softc *); | static int mwl_init(struct mwl_softc *); | ||||
▲ Show 20 Lines • Show All 1,129 Lines • ▼ Show 20 Lines | mwl_reset_vap(struct ieee80211vap *vap, int state) | ||||
/* re-setup beacons */ | /* re-setup beacons */ | ||||
if (state == IEEE80211_S_RUN && | if (state == IEEE80211_S_RUN && | ||||
(vap->iv_opmode == IEEE80211_M_HOSTAP || | (vap->iv_opmode == IEEE80211_M_HOSTAP || | ||||
vap->iv_opmode == IEEE80211_M_MBSS || | vap->iv_opmode == IEEE80211_M_MBSS || | ||||
vap->iv_opmode == IEEE80211_M_IBSS)) { | vap->iv_opmode == IEEE80211_M_IBSS)) { | ||||
mwl_setapmode(vap, vap->iv_bss->ni_chan); | mwl_setapmode(vap, vap->iv_bss->ni_chan); | ||||
mwl_hal_setnprotmode(hvap, | mwl_hal_setnprotmode(hvap, | ||||
MS(ic->ic_curhtprotmode, IEEE80211_HTINFO_OPMODE)); | _IEEE80211_MASKSHIFT(ic->ic_curhtprotmode, IEEE80211_HTINFO_OPMODE)); | ||||
return mwl_beacon_setup(vap); | return mwl_beacon_setup(vap); | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
/* | /* | ||||
* Reset the hardware w/o losing operational state. | * Reset the hardware w/o losing operational state. | ||||
* Used to reset or reload hardware state for a vap. | * Used to reset or reload hardware state for a vap. | ||||
▲ Show 20 Lines • Show All 615 Lines • ▼ Show 20 Lines | mwl_beacon_update(struct ieee80211vap *vap, int item) | ||||
KASSERT(hvap != NULL, ("no beacon")); | KASSERT(hvap != NULL, ("no beacon")); | ||||
switch (item) { | switch (item) { | ||||
case IEEE80211_BEACON_ERP: | case IEEE80211_BEACON_ERP: | ||||
mwl_updateslot(ic); | mwl_updateslot(ic); | ||||
break; | break; | ||||
case IEEE80211_BEACON_HTINFO: | case IEEE80211_BEACON_HTINFO: | ||||
mwl_hal_setnprotmode(hvap, | mwl_hal_setnprotmode(hvap, | ||||
MS(ic->ic_curhtprotmode, IEEE80211_HTINFO_OPMODE)); | _IEEE80211_MASKSHIFT(ic->ic_curhtprotmode, IEEE80211_HTINFO_OPMODE)); | ||||
break; | break; | ||||
case IEEE80211_BEACON_CAPS: | case IEEE80211_BEACON_CAPS: | ||||
case IEEE80211_BEACON_WME: | case IEEE80211_BEACON_WME: | ||||
case IEEE80211_BEACON_APPIE: | case IEEE80211_BEACON_APPIE: | ||||
case IEEE80211_BEACON_CSA: | case IEEE80211_BEACON_CSA: | ||||
break; | break; | ||||
case IEEE80211_BEACON_TIM: | case IEEE80211_BEACON_TIM: | ||||
/* NB: firmware always forms TIM */ | /* NB: firmware always forms TIM */ | ||||
▲ Show 20 Lines • Show All 1,164 Lines • ▼ Show 20 Lines | |||||
* this value is suitable for writing to the Format field | * this value is suitable for writing to the Format field | ||||
* of a tx descriptor. | * of a tx descriptor. | ||||
*/ | */ | ||||
static uint16_t | static uint16_t | ||||
mwl_calcformat(uint8_t rate, const struct ieee80211_node *ni) | mwl_calcformat(uint8_t rate, const struct ieee80211_node *ni) | ||||
{ | { | ||||
uint16_t fmt; | uint16_t fmt; | ||||
fmt = SM(3, EAGLE_TXD_ANTENNA) | fmt = _IEEE80211_SHIFTMASK(3, EAGLE_TXD_ANTENNA) | ||||
| (IEEE80211_IS_CHAN_HT40D(ni->ni_chan) ? | | (IEEE80211_IS_CHAN_HT40D(ni->ni_chan) ? | ||||
EAGLE_TXD_EXTCHAN_LO : EAGLE_TXD_EXTCHAN_HI); | EAGLE_TXD_EXTCHAN_LO : EAGLE_TXD_EXTCHAN_HI); | ||||
if (rate & IEEE80211_RATE_MCS) { /* HT MCS */ | if (rate & IEEE80211_RATE_MCS) { /* HT MCS */ | ||||
fmt |= EAGLE_TXD_FORMAT_HT | fmt |= EAGLE_TXD_FORMAT_HT | ||||
/* NB: 0x80 implicitly stripped from ucastrate */ | /* NB: 0x80 implicitly stripped from ucastrate */ | ||||
| SM(rate, EAGLE_TXD_RATE); | | _IEEE80211_SHIFTMASK(rate, EAGLE_TXD_RATE); | ||||
/* XXX short/long GI may be wrong; re-check */ | /* XXX short/long GI may be wrong; re-check */ | ||||
if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { | if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { | ||||
fmt |= EAGLE_TXD_CHW_40 | fmt |= EAGLE_TXD_CHW_40 | ||||
| (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40 ? | | (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40 ? | ||||
EAGLE_TXD_GI_SHORT : EAGLE_TXD_GI_LONG); | EAGLE_TXD_GI_SHORT : EAGLE_TXD_GI_LONG); | ||||
} else { | } else { | ||||
fmt |= EAGLE_TXD_CHW_20 | fmt |= EAGLE_TXD_CHW_20 | ||||
| (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20 ? | | (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20 ? | ||||
EAGLE_TXD_GI_SHORT : EAGLE_TXD_GI_LONG); | EAGLE_TXD_GI_SHORT : EAGLE_TXD_GI_LONG); | ||||
} | } | ||||
} else { /* legacy rate */ | } else { /* legacy rate */ | ||||
fmt |= EAGLE_TXD_FORMAT_LEGACY | fmt |= EAGLE_TXD_FORMAT_LEGACY | ||||
| SM(mwl_cvtlegacyrate(rate), EAGLE_TXD_RATE) | | _IEEE80211_SHIFTMASK(mwl_cvtlegacyrate(rate), EAGLE_TXD_RATE) | ||||
| EAGLE_TXD_CHW_20 | | EAGLE_TXD_CHW_20 | ||||
/* XXX iv_flags & IEEE80211_F_SHPREAMBLE? */ | /* XXX iv_flags & IEEE80211_F_SHPREAMBLE? */ | ||||
| (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE ? | | (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE ? | ||||
EAGLE_TXD_PREAMBLE_SHORT : EAGLE_TXD_PREAMBLE_LONG); | EAGLE_TXD_PREAMBLE_SHORT : EAGLE_TXD_PREAMBLE_LONG); | ||||
} | } | ||||
return fmt; | return fmt; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 284 Lines • ▼ Show 20 Lines | if (sc->sc_debug & MWL_DEBUG_XMIT_DESC) | ||||
mwl_printtxbuf(bf, txq->qnum, nreaped); | mwl_printtxbuf(bf, txq->qnum, nreaped); | ||||
#endif | #endif | ||||
ni = bf->bf_node; | ni = bf->bf_node; | ||||
if (ni != NULL) { | if (ni != NULL) { | ||||
an = MWL_NODE(ni); | an = MWL_NODE(ni); | ||||
status = le32toh(ds->Status); | status = le32toh(ds->Status); | ||||
if (status & EAGLE_TXD_STATUS_OK) { | if (status & EAGLE_TXD_STATUS_OK) { | ||||
uint16_t Format = le16toh(ds->Format); | uint16_t Format = le16toh(ds->Format); | ||||
uint8_t txant = MS(Format, EAGLE_TXD_ANTENNA); | uint8_t txant = _IEEE80211_MASKSHIFT(Format, EAGLE_TXD_ANTENNA); | ||||
sc->sc_stats.mst_ant_tx[txant]++; | sc->sc_stats.mst_ant_tx[txant]++; | ||||
if (status & EAGLE_TXD_STATUS_OK_RETRY) | if (status & EAGLE_TXD_STATUS_OK_RETRY) | ||||
sc->sc_stats.mst_tx_retries++; | sc->sc_stats.mst_tx_retries++; | ||||
if (status & EAGLE_TXD_STATUS_OK_MORE_RETRY) | if (status & EAGLE_TXD_STATUS_OK_MORE_RETRY) | ||||
sc->sc_stats.mst_tx_mretries++; | sc->sc_stats.mst_tx_mretries++; | ||||
if (txq->qnum >= MWL_WME_AC_VO) | if (txq->qnum >= MWL_WME_AC_VO) | ||||
ic->ic_wme.wme_hipri_traffic++; | ic->ic_wme.wme_hipri_traffic++; | ||||
ni->ni_txrate = MS(Format, EAGLE_TXD_RATE); | ni->ni_txrate = _IEEE80211_MASKSHIFT(Format, EAGLE_TXD_RATE); | ||||
if ((Format & EAGLE_TXD_FORMAT_HT) == 0) { | if ((Format & EAGLE_TXD_FORMAT_HT) == 0) { | ||||
ni->ni_txrate = mwl_cvtlegacyrix( | ni->ni_txrate = mwl_cvtlegacyrix( | ||||
ni->ni_txrate); | ni->ni_txrate); | ||||
} else | } else | ||||
ni->ni_txrate |= IEEE80211_RATE_MCS; | ni->ni_txrate |= IEEE80211_RATE_MCS; | ||||
sc->sc_stats.mst_tx_rate = ni->ni_txrate; | sc->sc_stats.mst_tx_rate = ni->ni_txrate; | ||||
} else { | } else { | ||||
if (status & EAGLE_TXD_STATUS_FAILED_LINK_ERROR) | if (status & EAGLE_TXD_STATUS_FAILED_LINK_ERROR) | ||||
▲ Show 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | mwl_recv_action(struct ieee80211_node *ni, const struct ieee80211_frame *wh, | ||||
ia = (const struct ieee80211_action *) frm; | ia = (const struct ieee80211_action *) frm; | ||||
if (ia->ia_category == IEEE80211_ACTION_CAT_HT && | if (ia->ia_category == IEEE80211_ACTION_CAT_HT && | ||||
ia->ia_action == IEEE80211_ACTION_HT_MIMOPWRSAVE) { | ia->ia_action == IEEE80211_ACTION_HT_MIMOPWRSAVE) { | ||||
const struct ieee80211_action_ht_mimopowersave *mps = | const struct ieee80211_action_ht_mimopowersave *mps = | ||||
(const struct ieee80211_action_ht_mimopowersave *) ia; | (const struct ieee80211_action_ht_mimopowersave *) ia; | ||||
mwl_hal_setmimops(sc->sc_mh, ni->ni_macaddr, | mwl_hal_setmimops(sc->sc_mh, ni->ni_macaddr, | ||||
mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_ENA, | mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_ENA, | ||||
MS(mps->am_control, IEEE80211_A_HT_MIMOPWRSAVE_MODE)); | _IEEE80211_MASKSHIFT(mps->am_control, IEEE80211_A_HT_MIMOPWRSAVE_MODE)); | ||||
return 0; | return 0; | ||||
} else | } else | ||||
return sc->sc_recv_action(ni, wh, frm, efrm); | return sc->sc_recv_action(ni, wh, frm, efrm); | ||||
} | } | ||||
static int | static int | ||||
mwl_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, | mwl_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, | ||||
int dialogtoken, int baparamset, int batimeout) | int dialogtoken, int baparamset, int batimeout) | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | if (code == IEEE80211_STATUS_SUCCESS) { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
int bufsiz, error; | int bufsiz, error; | ||||
/* | /* | ||||
* Tell the firmware to setup the BA stream; | * Tell the firmware to setup the BA stream; | ||||
* we know resources are available because we | * we know resources are available because we | ||||
* pre-allocated one before forming the request. | * pre-allocated one before forming the request. | ||||
*/ | */ | ||||
bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); | bufsiz = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ); | ||||
if (bufsiz == 0) | if (bufsiz == 0) | ||||
bufsiz = IEEE80211_AGGR_BAWMAX; | bufsiz = IEEE80211_AGGR_BAWMAX; | ||||
error = mwl_hal_bastream_create(MWL_VAP(vap)->mv_hvap, | error = mwl_hal_bastream_create(MWL_VAP(vap)->mv_hvap, | ||||
bas->bastream, bufsiz, bufsiz, tap->txa_start); | bas->bastream, bufsiz, bufsiz, tap->txa_start); | ||||
if (error != 0) { | if (error != 0) { | ||||
/* | /* | ||||
* Setup failed, return immediately so no a-mpdu | * Setup failed, return immediately so no a-mpdu | ||||
* aggregation will be done. | * aggregation will be done. | ||||
▲ Show 20 Lines • Show All 1,163 Lines • Show Last 20 Lines |