Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/mwl/if_mwl.c
Show First 20 Lines • Show All 139 Lines • ▼ Show 20 Lines | static void mwl_node_getmimoinfo(const struct ieee80211_node *, | ||||
struct ieee80211_mimo_info *); | struct ieee80211_mimo_info *); | ||||
static int mwl_rxbuf_init(struct mwl_softc *, struct mwl_rxbuf *); | static int mwl_rxbuf_init(struct mwl_softc *, struct mwl_rxbuf *); | ||||
static void mwl_rx_proc(void *, int); | static void mwl_rx_proc(void *, int); | ||||
static void mwl_txq_init(struct mwl_softc *sc, struct mwl_txq *, int); | static void mwl_txq_init(struct mwl_softc *sc, struct mwl_txq *, int); | ||||
static int mwl_tx_setup(struct mwl_softc *, int, int); | static int mwl_tx_setup(struct mwl_softc *, int, int); | ||||
static int mwl_wme_update(struct ieee80211com *); | static int mwl_wme_update(struct ieee80211com *); | ||||
static void mwl_tx_cleanupq(struct mwl_softc *, struct mwl_txq *); | static void mwl_tx_cleanupq(struct mwl_softc *, struct mwl_txq *); | ||||
static void mwl_tx_cleanup(struct mwl_softc *); | static void mwl_tx_cleanup(struct mwl_softc *); | ||||
static uint16_t mwl_calcformat(uint8_t rate, const struct ieee80211_node *); | static uint16_t mwl_calcformat(uint16_t, const struct ieee80211_node *); | ||||
static int mwl_tx_start(struct mwl_softc *, struct ieee80211_node *, | static int mwl_tx_start(struct mwl_softc *, struct ieee80211_node *, | ||||
struct mwl_txbuf *, struct mbuf *); | struct mwl_txbuf *, struct mbuf *); | ||||
static void mwl_tx_proc(void *, int); | static void mwl_tx_proc(void *, int); | ||||
static int mwl_chan_set(struct mwl_softc *, struct ieee80211_channel *); | static int mwl_chan_set(struct mwl_softc *, struct ieee80211_channel *); | ||||
static void mwl_draintxq(struct mwl_softc *); | static void mwl_draintxq(struct mwl_softc *); | ||||
static void mwl_cleartxq(struct mwl_softc *, struct ieee80211vap *); | static void mwl_cleartxq(struct mwl_softc *, struct ieee80211vap *); | ||||
static int mwl_recv_action(struct ieee80211_node *, | static int mwl_recv_action(struct ieee80211_node *, | ||||
const struct ieee80211_frame *, | const struct ieee80211_frame *, | ||||
▲ Show 20 Lines • Show All 841 Lines • ▼ Show 20 Lines | |||||
* Called after a channel change. | * Called after a channel change. | ||||
*/ | */ | ||||
static int | static int | ||||
mwl_setcurchanrates(struct mwl_softc *sc) | mwl_setcurchanrates(struct mwl_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
const struct ieee80211_rateset *rs; | const struct ieee80211_rateset *rs; | ||||
MWL_HAL_TXRATE rates; | MWL_HAL_TXRATE rates; | ||||
uint8_t rv; | |||||
memset(&rates, 0, sizeof(rates)); | memset(&rates, 0, sizeof(rates)); | ||||
rs = ieee80211_get_suprates(ic, ic->ic_curchan); | rs = ieee80211_get_suprates(ic, ic->ic_curchan); | ||||
rv = ieee80211_convert_to_legacy_rate(rs->rates[0].rs_index); | |||||
/* rate used to send management frames */ | /* rate used to send management frames */ | ||||
rates.MgtRate = rs->rs_rates[0] & IEEE80211_RATE_VAL; | rates.MgtRate = rv; | ||||
/* rate used to send multicast frames */ | /* rate used to send multicast frames */ | ||||
rates.McastRate = rates.MgtRate; | rates.McastRate = rates.MgtRate; | ||||
return mwl_hal_settxrate_auto(sc->sc_mh, &rates); | return mwl_hal_settxrate_auto(sc->sc_mh, &rates); | ||||
} | } | ||||
/* | /* | ||||
* Inform firmware of tx rate parameters. Called whenever | * Inform firmware of tx rate parameters. Called whenever | ||||
* user-settable params change and after a channel change. | * user-settable params change and after a channel change. | ||||
*/ | */ | ||||
static int | static int | ||||
mwl_setrates(struct ieee80211vap *vap) | mwl_setrates(struct ieee80211vap *vap) | ||||
{ | { | ||||
struct mwl_vap *mvp = MWL_VAP(vap); | struct mwl_vap *mvp = MWL_VAP(vap); | ||||
struct ieee80211_node *ni = vap->iv_bss; | struct ieee80211_node *ni = vap->iv_bss; | ||||
const struct ieee80211_txparam *tp = ni->ni_txparms; | const struct ieee80211_txparam_vht *tp = ni->ni_txparms; | ||||
MWL_HAL_TXRATE rates; | MWL_HAL_TXRATE rates; | ||||
KASSERT(vap->iv_state == IEEE80211_S_RUN, ("state %d", vap->iv_state)); | KASSERT(vap->iv_state == IEEE80211_S_RUN, ("state %d", vap->iv_state)); | ||||
/* | /* | ||||
* Update the h/w rate map. | * Update the h/w rate map. | ||||
* NB: 0x80 for MCS is passed through unchanged | * NB: 0x80 for MCS is passed through unchanged | ||||
*/ | */ | ||||
memset(&rates, 0, sizeof(rates)); | memset(&rates, 0, sizeof(rates)); | ||||
/* rate used to send management frames */ | /* rate used to send management frames */ | ||||
rates.MgtRate = tp->mgmtrate; | rates.MgtRate = ieee80211_convert_to_legacy_rate(tp->mgmtrate); | ||||
/* rate used to send multicast frames */ | /* rate used to send multicast frames */ | ||||
rates.McastRate = tp->mcastrate; | rates.McastRate = ieee80211_convert_to_legacy_rate(tp->mcastrate); | ||||
/* while here calculate EAPOL fixed rate cookie */ | /* while here calculate EAPOL fixed rate cookie */ | ||||
mvp->mv_eapolformat = htole16(mwl_calcformat(rates.MgtRate, ni)); | mvp->mv_eapolformat = htole16(mwl_calcformat(tp->mgmtrate, ni)); | ||||
return mwl_hal_settxrate(mvp->mv_hvap, | return mwl_hal_settxrate(mvp->mv_hvap, | ||||
tp->ucastrate != IEEE80211_FIXED_RATE_NONE ? | tp->ucastrate != IEEE80211_RATE_NONEXISTENT ? | ||||
RATE_FIXED : RATE_AUTO, &rates); | RATE_FIXED : RATE_AUTO, &rates); | ||||
} | } | ||||
/* | /* | ||||
* Setup a fixed xmit rate cookie for EAPOL frames. | * Setup a fixed xmit rate cookie for EAPOL frames. | ||||
*/ | */ | ||||
static void | static void | ||||
mwl_seteapolformat(struct ieee80211vap *vap) | mwl_seteapolformat(struct ieee80211vap *vap) | ||||
{ | { | ||||
struct mwl_vap *mvp = MWL_VAP(vap); | struct mwl_vap *mvp = MWL_VAP(vap); | ||||
struct ieee80211_node *ni = vap->iv_bss; | struct ieee80211_node *ni = vap->iv_bss; | ||||
enum ieee80211_phymode mode; | enum ieee80211_phymode mode; | ||||
uint8_t rate; | uint16_t rate_idx; | ||||
KASSERT(vap->iv_state == IEEE80211_S_RUN, ("state %d", vap->iv_state)); | KASSERT(vap->iv_state == IEEE80211_S_RUN, ("state %d", vap->iv_state)); | ||||
mode = ieee80211_chan2mode(ni->ni_chan); | mode = ieee80211_chan2mode(ni->ni_chan); | ||||
/* | /* | ||||
* Use legacy rates when operating a mixed HT+non-HT bss. | * Use legacy rates when operating a mixed HT+non-HT bss. | ||||
* NB: this may violate POLA for sta and wds vap's. | * NB: this may violate POLA for sta and wds vap's. | ||||
*/ | */ | ||||
if (mode == IEEE80211_MODE_11NA && | if (mode == IEEE80211_MODE_11NA && | ||||
(vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0) | (vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0) | ||||
rate = vap->iv_txparms[IEEE80211_MODE_11A].mgmtrate; | rate_idx = vap->iv_txparms[IEEE80211_MODE_11A].mgmtrate; | ||||
else if (mode == IEEE80211_MODE_11NG && | else if (mode == IEEE80211_MODE_11NG && | ||||
(vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0) | (vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0) | ||||
rate = vap->iv_txparms[IEEE80211_MODE_11G].mgmtrate; | rate_idx = vap->iv_txparms[IEEE80211_MODE_11G].mgmtrate; | ||||
else | else | ||||
rate = vap->iv_txparms[mode].mgmtrate; | rate_idx = vap->iv_txparms[mode].mgmtrate; | ||||
mvp->mv_eapolformat = htole16(mwl_calcformat(rate, ni)); | mvp->mv_eapolformat = htole16(mwl_calcformat(rate_idx, ni)); | ||||
} | } | ||||
/* | /* | ||||
* Map SKU+country code to region code for radar bin'ing. | * Map SKU+country code to region code for radar bin'ing. | ||||
*/ | */ | ||||
static int | static int | ||||
mwl_map2regioncode(const struct ieee80211_regdomain *rd) | mwl_map2regioncode(const struct ieee80211_regdomain *rd) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,953 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Calculate fixed tx rate information per client state; | * Calculate fixed tx rate information per client state; | ||||
* 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(uint16_t rate_idx, const struct ieee80211_node *ni) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
uint16_t fmt; | uint16_t fmt; | ||||
rate = ieee80211_get_rate(rate_idx); | |||||
fmt = SM(3, EAGLE_TXD_ANTENNA) | fmt = SM(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->type == IEEE80211_T_HT) { | ||||
fmt |= EAGLE_TXD_FORMAT_HT | fmt |= EAGLE_TXD_FORMAT_HT | ||||
/* NB: 0x80 implicitly stripped from ucastrate */ | | SM(rate->value, EAGLE_TXD_RATE); | ||||
| SM(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) | | SM(mwl_cvtlegacyrate(rate->value), 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 171 Lines • ▼ Show 20 Lines | case IEEE80211_FC0_TYPE_MGT: | ||||
sc->sc_stats.mst_tx_mgmt++; | sc->sc_stats.mst_tx_mgmt++; | ||||
/* fall thru... */ | /* fall thru... */ | ||||
case IEEE80211_FC0_TYPE_CTL: | case IEEE80211_FC0_TYPE_CTL: | ||||
/* NB: assign to BE q to avoid bursting */ | /* NB: assign to BE q to avoid bursting */ | ||||
ds->TxPriority = MWL_WME_AC_BE; | ds->TxPriority = MWL_WME_AC_BE; | ||||
break; | break; | ||||
case IEEE80211_FC0_TYPE_DATA: | case IEEE80211_FC0_TYPE_DATA: | ||||
if (!ismcast) { | if (!ismcast) { | ||||
const struct ieee80211_txparam *tp = ni->ni_txparms; | const struct ieee80211_txparam_vht *tp; | ||||
/* | /* | ||||
* EAPOL frames get forced to a fixed rate and w/o | * EAPOL frames get forced to a fixed rate and w/o | ||||
* aggregation; otherwise check for any fixed rate | * aggregation; otherwise check for any fixed rate | ||||
* for the client (may depend on association state). | * for the client (may depend on association state). | ||||
*/ | */ | ||||
tp = ni->ni_txparms; | |||||
if (m0->m_flags & M_EAPOL) { | if (m0->m_flags & M_EAPOL) { | ||||
const struct mwl_vap *mvp = MWL_VAP_CONST(vap); | const struct mwl_vap *mvp = MWL_VAP_CONST(vap); | ||||
ds->Format = mvp->mv_eapolformat; | ds->Format = mvp->mv_eapolformat; | ||||
ds->pad = htole16( | ds->pad = htole16( | ||||
EAGLE_TXD_FIXED_RATE | EAGLE_TXD_DONT_AGGR); | EAGLE_TXD_FIXED_RATE | EAGLE_TXD_DONT_AGGR); | ||||
} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { | } else if (tp->ucastrate != IEEE80211_RATE_NONEXISTENT) { | ||||
/* XXX pre-calculate per node */ | /* XXX pre-calculate per node */ | ||||
ds->Format = htole16( | ds->Format = htole16( | ||||
mwl_calcformat(tp->ucastrate, ni)); | mwl_calcformat(tp->ucastrate, ni)); | ||||
ds->pad = htole16(EAGLE_TXD_FIXED_RATE); | ds->pad = htole16(EAGLE_TXD_FIXED_RATE); | ||||
} | } | ||||
/* NB: EAPOL frames will never have qos set */ | /* NB: EAPOL frames will never have qos set */ | ||||
if (qos == 0) | if (qos == 0) | ||||
ds->TxPriority = txq->qnum; | ds->TxPriority = txq->qnum; | ||||
Show All 37 Lines | #endif | ||||
MWL_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | MWL_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
sc->sc_tx_timer = 5; | sc->sc_tx_timer = 5; | ||||
MWL_TXQ_UNLOCK(txq); | MWL_TXQ_UNLOCK(txq); | ||||
return 0; | return 0; | ||||
} | } | ||||
static __inline int | static __inline uint16_t | ||||
mwl_cvtlegacyrix(int rix) | mwl_cvtlegacyrix(int rix) | ||||
{ | { | ||||
static const int ieeerates[] = | static const uint16_t ieeerates[] = { | ||||
{ 2, 4, 11, 22, 44, 12, 18, 24, 36, 48, 72, 96, 108 }; | IEEE80211_RATE_INDEX_CCK1, IEEE80211_RATE_INDEX_CCK2, | ||||
IEEE80211_RATE_INDEX_CCK5, IEEE80211_RATE_INDEX_CCK11, | |||||
IEEE80211_RATE_INDEX_PBCC22, IEEE80211_RATE_INDEX_OFDM6, | |||||
IEEE80211_RATE_INDEX_OFDM9, IEEE80211_RATE_INDEX_OFDM12, | |||||
IEEE80211_RATE_INDEX_OFDM18, IEEE80211_RATE_INDEX_OFDM24, | |||||
IEEE80211_RATE_INDEX_OFDM36, IEEE80211_RATE_INDEX_OFDM48, | |||||
IEEE80211_RATE_INDEX_OFDM54 | |||||
}; | |||||
return (rix < nitems(ieeerates) ? ieeerates[rix] : 0); | return (rix < nitems(ieeerates) ? ieeerates[rix] : 0); | ||||
} | } | ||||
/* | /* | ||||
* Process completed xmit descriptors from the specified queue. | * Process completed xmit descriptors from the specified queue. | ||||
*/ | */ | ||||
static int | static int | ||||
mwl_tx_processq(struct mwl_softc *sc, struct mwl_txq *txq) | mwl_tx_processq(struct mwl_softc *sc, struct mwl_txq *txq) | ||||
{ | { | ||||
#define EAGLE_TXD_STATUS_MCAST \ | #define EAGLE_TXD_STATUS_MCAST \ | ||||
(EAGLE_TXD_STATUS_MULTICAST_TX | EAGLE_TXD_STATUS_BROADCAST_TX) | (EAGLE_TXD_STATUS_MULTICAST_TX | EAGLE_TXD_STATUS_BROADCAST_TX) | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct mwl_txbuf *bf; | struct mwl_txbuf *bf; | ||||
struct mwl_txdesc *ds; | struct mwl_txdesc *ds; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mwl_node *an; | struct mwl_node *an; | ||||
int nreaped; | int nreaped, max_mcs; | ||||
uint32_t status; | uint32_t status; | ||||
uint8_t rv; | |||||
DPRINTF(sc, MWL_DEBUG_TX_PROC, "%s: tx queue %u\n", __func__, txq->qnum); | DPRINTF(sc, MWL_DEBUG_TX_PROC, "%s: tx queue %u\n", __func__, txq->qnum); | ||||
max_mcs = IEEE80211_HT_MCS_CHAIN * ic->ic_txstream; | |||||
for (nreaped = 0;; nreaped++) { | for (nreaped = 0;; nreaped++) { | ||||
MWL_TXQ_LOCK(txq); | MWL_TXQ_LOCK(txq); | ||||
bf = STAILQ_FIRST(&txq->active); | bf = STAILQ_FIRST(&txq->active); | ||||
if (bf == NULL) { | if (bf == NULL) { | ||||
MWL_TXQ_UNLOCK(txq); | MWL_TXQ_UNLOCK(txq); | ||||
break; | break; | ||||
} | } | ||||
ds = bf->bf_desc; | ds = bf->bf_desc; | ||||
Show All 20 Lines | if (ni != NULL) { | ||||
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); | rv = MS(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(rv); | ||||
else if (rv < max_mcs) { | |||||
ni->ni_txrate = | |||||
IEEE80211_RATE_INDEX_HT(rv); | |||||
} | |||||
sc->sc_stats.mst_tx_rate = | |||||
ieee80211_convert_to_legacy_rate( | |||||
ni->ni_txrate); | ni->ni_txrate); | ||||
} else | |||||
ni->ni_txrate |= IEEE80211_RATE_MCS; | |||||
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) | ||||
sc->sc_stats.mst_tx_linkerror++; | sc->sc_stats.mst_tx_linkerror++; | ||||
if (status & EAGLE_TXD_STATUS_FAILED_XRETRY) | if (status & EAGLE_TXD_STATUS_FAILED_XRETRY) | ||||
sc->sc_stats.mst_tx_xretries++; | sc->sc_stats.mst_tx_xretries++; | ||||
if (status & EAGLE_TXD_STATUS_FAILED_AGING) | if (status & EAGLE_TXD_STATUS_FAILED_AGING) | ||||
sc->sc_stats.mst_tx_aging++; | sc->sc_stats.mst_tx_aging++; | ||||
if (bf->bf_m->m_flags & M_FF) | if (bf->bf_m->m_flags & M_FF) | ||||
▲ Show 20 Lines • Show All 567 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Convert a legacy rate set to a firmware bitmask. | * Convert a legacy rate set to a firmware bitmask. | ||||
*/ | */ | ||||
static uint32_t | static uint32_t | ||||
get_rate_bitmap(const struct ieee80211_rateset *rs) | get_rate_bitmap(const struct ieee80211_rateset *rs) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
uint32_t rates; | uint32_t rates; | ||||
int i; | int i; | ||||
rates = 0; | rates = 0; | ||||
for (i = 0; i < rs->rs_nrates; i++) | for (i = 0; i < rs->rs_nrates; i++) | ||||
switch (rs->rs_rates[i] & IEEE80211_RATE_VAL) { | rate = ieee80211_get_rate(rs->rates[i].rs_index); | ||||
switch (rate->value) { | |||||
case 2: rates |= 0x001; break; | case 2: rates |= 0x001; break; | ||||
case 4: rates |= 0x002; break; | case 4: rates |= 0x002; break; | ||||
case 11: rates |= 0x004; break; | case 11: rates |= 0x004; break; | ||||
case 22: rates |= 0x008; break; | case 22: rates |= 0x008; break; | ||||
case 44: rates |= 0x010; break; | case 44: rates |= 0x010; break; | ||||
case 12: rates |= 0x020; break; | case 12: rates |= 0x020; break; | ||||
case 18: rates |= 0x040; break; | case 18: rates |= 0x040; break; | ||||
case 24: rates |= 0x080; break; | case 24: rates |= 0x080; break; | ||||
case 36: rates |= 0x100; break; | case 36: rates |= 0x100; break; | ||||
case 48: rates |= 0x200; break; | case 48: rates |= 0x200; break; | ||||
case 72: rates |= 0x400; break; | case 72: rates |= 0x400; break; | ||||
case 96: rates |= 0x800; break; | case 96: rates |= 0x800; break; | ||||
case 108: rates |= 0x1000; break; | case 108: rates |= 0x1000; break; | ||||
} | } | ||||
return rates; | return rates; | ||||
} | } | ||||
/* | /* | ||||
* Construct an HT firmware bitmask from an HT rate set. | * Construct an HT firmware bitmask from an HT rate set. | ||||
*/ | */ | ||||
static uint32_t | static uint32_t | ||||
get_htrate_bitmap(const struct ieee80211_htrateset *rs) | get_htrate_bitmap(const struct ieee80211_htrateset *rs) | ||||
{ | { | ||||
uint32_t rates; | |||||
int i; | |||||
rates = 0; | return (rs->rs_bitmap[0] | (rs->rs_bitmap[1] << 8)); | ||||
for (i = 0; i < rs->rs_nrates; i++) { | |||||
if (rs->rs_rates[i] < 16) | |||||
rates |= 1<<rs->rs_rates[i]; | |||||
} | |||||
return rates; | |||||
} | } | ||||
/* | /* | ||||
* Craft station database entry for station. | * Craft station database entry for station. | ||||
* NB: use host byte order here, the hal handles byte swapping. | * NB: use host byte order here, the hal handles byte swapping. | ||||
*/ | */ | ||||
static MWL_HAL_PEERINFO * | static MWL_HAL_PEERINFO * | ||||
mkpeerinfo(MWL_HAL_PEERINFO *pi, const struct ieee80211_node *ni) | mkpeerinfo(MWL_HAL_PEERINFO *pi, const struct ieee80211_node *ni) | ||||
▲ Show 20 Lines • Show All 822 Lines • Show Last 20 Lines |