Date: Sun, 8 May 2011 11:49:50 +0000 (UTC) From: Bernhard Schmidt <bschmidt@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r221648 - head/sys/dev/iwn Message-ID: <201105081149.p48BnoHC044507@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bschmidt Date: Sun May 8 11:49:50 2011 New Revision: 221648 URL: http://svn.freebsd.org/changeset/base/221648 Log: Prepare for transmitting frames at MCS rates: - instead of calling iwn_plcp_signal() for every frame, map the expected value directly within wn->ridx - concat plcp, rflags and xrflags, there is no clean byte boundary within the flags, for example the antenna setting uses bit 6, 7 and 8 - there is still need for a custom rate to plcp mapping, as those expected by the hardware are not conform to the std Modified: head/sys/dev/iwn/if_iwn.c head/sys/dev/iwn/if_iwnreg.h head/sys/dev/iwn/if_iwnvar.h Modified: head/sys/dev/iwn/if_iwn.c ============================================================================== --- head/sys/dev/iwn/if_iwn.c Sun May 8 11:42:51 2011 (r221647) +++ head/sys/dev/iwn/if_iwn.c Sun May 8 11:49:50 2011 (r221648) @@ -199,7 +199,6 @@ static void iwn5000_update_sched(struct #ifdef notyet static void iwn5000_reset_sched(struct iwn_softc *, int, int); #endif -static uint8_t iwn_plcp_signal(int); static int iwn_tx_data(struct iwn_softc *, struct mbuf *, struct ieee80211_node *); static int iwn_tx_data_raw(struct iwn_softc *, struct mbuf *, @@ -2094,15 +2093,48 @@ iwn_node_alloc(struct ieee80211vap *vap, return malloc(sizeof (struct iwn_node), M_80211_NODE,M_NOWAIT | M_ZERO); } +static __inline int +rate2plcp(int rate) +{ + switch (rate & 0xff) { + case 12: return 0xd; + case 18: return 0xf; + case 24: return 0x5; + case 36: return 0x7; + case 48: return 0x9; + case 72: return 0xb; + case 96: return 0x1; + case 108: return 0x3; + case 2: return 10; + case 4: return 20; + case 11: return 55; + case 22: return 110; + } + return 0; +} + static void iwn_newassoc(struct ieee80211_node *ni, int isnew) { + struct ieee80211com *ic = ni->ni_ic; + struct iwn_softc *sc = ic->ic_ifp->if_softc; struct iwn_node *wn = (void *)ni; - int ridx, i; + uint8_t txant; + int i, plcp, rate, ridx; + + /* Use the first valid TX antenna. */ + txant = IWN_LSB(sc->txchainmask); for (i = 0; i < ni->ni_rates.rs_nrates; i++) { - ridx = iwn_plcp_signal(ni->ni_rates.rs_rates[i]); - wn->ridx[i] = ridx; + rate = ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL; + plcp = rate2plcp(rate); + ridx = ic->ic_rt->rateCodeToIndex[rate]; + + if (ridx < IWN_RIDX_OFDM6 && + IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) + plcp |= IWN_RFLAG_CCK; + plcp |= IWN_RFLAG_ANT(txant); + wn->ridx[rate] = htole32(plcp); } } @@ -3087,18 +3119,6 @@ iwn5000_reset_sched(struct iwn_softc *sc } #endif -static uint8_t -iwn_plcp_signal(int rate) { - int i; - - for (i = 0; i < IWN_RIDX_MAX + 1; i++) { - if ((rate & IEEE80211_RATE_VAL) == iwn_rates[i].rate) - return i; - } - - return 0; -} - static int iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { @@ -3111,7 +3131,6 @@ iwn_tx_data(struct iwn_softc *sc, struct struct iwn_tx_data *data; struct iwn_tx_cmd *cmd; struct iwn_cmd_data *tx; - const struct iwn_rate *rinfo; struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; struct mbuf *m1; @@ -3155,8 +3174,7 @@ iwn_tx_data(struct iwn_softc *sc, struct (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } - ridx = iwn_plcp_signal(rate); - rinfo = &iwn_rates[ridx]; + ridx = ic->ic_rt->rateCodeToIndex[rate]; /* Encrypt the frame if need be. */ if (wh->i_fc[1] & IEEE80211_FC1_WEP) { @@ -3175,7 +3193,7 @@ iwn_tx_data(struct iwn_softc *sc, struct struct iwn_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; - tap->wt_rate = rinfo->rate; + tap->wt_rate = rate; if (k != NULL) tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; @@ -3262,14 +3280,13 @@ iwn_tx_data(struct iwn_softc *sc, struct tx->rts_ntries = 60; tx->data_ntries = 15; tx->lifetime = htole32(IWN_LIFETIME_INFINITE); - tx->plcp = rinfo->plcp; - tx->rflags = rinfo->flags; + tx->rate = wn->ridx[rate]; if (tx->id == sc->broadcast_id) { /* Group or management frame. */ tx->linkq = 0; /* XXX Alternate between antenna A and B? */ txant = IWN_LSB(sc->txchainmask); - tx->rflags |= IWN_RFLAG_ANT(txant); + tx->rate |= htole32(IWN_RFLAG_ANT(txant)); } else { tx->linkq = ni->ni_rates.rs_nrates - ridx - 1; flags |= IWN_TX_LINKQ; /* enable MRR */ @@ -3364,7 +3381,6 @@ static int iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) { - const struct iwn_rate *rinfo; struct ifnet *ifp = sc->sc_ifp; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ifp->if_l2com; @@ -3395,13 +3411,12 @@ iwn_tx_data_raw(struct iwn_softc *sc, st /* Choose a TX rate index. */ rate = params->ibp_rate0; - if (!ieee80211_isratevalid(ic->ic_rt, rate)) { + ridx = ic->ic_rt->rateCodeToIndex[rate]; + if (ridx == (uint8_t)-1) { /* XXX fall back to mcast/mgmt rate? */ m_freem(m); return EINVAL; } - ridx = iwn_plcp_signal(rate); - rinfo = &iwn_rates[ridx]; totlen = m->m_pkthdr.len; @@ -3472,12 +3487,14 @@ iwn_tx_data_raw(struct iwn_softc *sc, st tx->rts_ntries = params->ibp_try1; tx->data_ntries = params->ibp_try0; tx->lifetime = htole32(IWN_LIFETIME_INFINITE); - tx->plcp = rinfo->plcp; - tx->rflags = rinfo->flags; + tx->rate = htole32(rate2plcp(rate)); + if (ridx < IWN_RIDX_OFDM6 && + IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) + tx->rate |= htole32(IWN_RFLAG_CCK); /* Group or management frame. */ tx->linkq = 0; txant = IWN_LSB(sc->txchainmask); - tx->rflags |= IWN_RFLAG_ANT(txant); + tx->rate |= htole32(IWN_RFLAG_ANT(txant)); /* Set physical address of "scratch area". */ tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr)); tx->hiaddr = IWN_HIADDR(data->scratch_paddr); @@ -3817,9 +3834,8 @@ iwn_set_link_quality(struct iwn_softc *s struct iwn_node *wn = (void *)ni; struct ieee80211_rateset *rs = &ni->ni_rates; struct iwn_cmd_link_quality linkq; - const struct iwn_rate *rinfo; uint8_t txant; - int i, txrate; + int i, rate, txrate; /* Use the first valid TX antenna. */ txant = IWN_LSB(sc->txchainmask); @@ -3835,10 +3851,9 @@ iwn_set_link_quality(struct iwn_softc *s /* Start at highest available bit-rate. */ txrate = rs->rs_nrates - 1; for (i = 0; i < IWN_MAX_TX_RETRIES; i++) { - rinfo = &iwn_rates[wn->ridx[txrate]]; - linkq.retry[i].plcp = rinfo->plcp; - linkq.retry[i].rflags = rinfo->flags; - linkq.retry[i].rflags |= IWN_RFLAG_ANT(txant); + rate = rs->rs_rates[txrate] & IEEE80211_RATE_VAL; + linkq.retry[i] = wn->ridx[rate]; + /* Next retry at immediate lower bit-rate. */ if (txrate > 0) txrate--; @@ -3857,7 +3872,6 @@ iwn_add_broadcast_node(struct iwn_softc struct ieee80211com *ic = ifp->if_l2com; struct iwn_node_info node; struct iwn_cmd_link_quality linkq; - const struct iwn_rate *rinfo; uint8_t txant; int i, error; @@ -3881,16 +3895,13 @@ iwn_add_broadcast_node(struct iwn_softc /* Use lowest mandatory bit-rate. */ if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) - rinfo = &iwn_rates[IWN_RIDX_OFDM6]; + linkq.retry[0] = htole32(0xd); else - rinfo = &iwn_rates[IWN_RIDX_CCK1]; - linkq.retry[0].plcp = rinfo->plcp; - linkq.retry[0].rflags = rinfo->flags; - linkq.retry[0].rflags |= IWN_RFLAG_ANT(txant); + linkq.retry[0] = htole32(10 | IWN_RFLAG_CCK); + linkq.retry[0] |= htole32(IWN_RFLAG_ANT(txant)); /* Use same bit-rate for all TX retries. */ for (i = 1; i < IWN_MAX_TX_RETRIES; i++) { - linkq.retry[i].plcp = linkq.retry[0].plcp; - linkq.retry[i].rflags = linkq.retry[0].rflags; + linkq.retry[i] = linkq.retry[0]; } return iwn_cmd(sc, IWN_CMD_LINK_QUALITY, &linkq, sizeof linkq, async); } @@ -4991,18 +5002,17 @@ iwn_scan(struct iwn_softc *sc) if (IEEE80211_IS_CHAN_A(ic->ic_curchan)) { /* Send probe requests at 6Mbps. */ - tx->plcp = iwn_rates[IWN_RIDX_OFDM6].plcp; + tx->rate = htole32(0xd); rs = &ic->ic_sup_rates[IEEE80211_MODE_11A]; } else { hdr->flags = htole32(IWN_RXON_24GHZ | IWN_RXON_AUTO); /* Send probe requests at 1Mbps. */ - tx->plcp = iwn_rates[IWN_RIDX_CCK1].plcp; - tx->rflags = IWN_RFLAG_CCK; + tx->rate = htole32(10 | IWN_RFLAG_CCK); rs = &ic->ic_sup_rates[IEEE80211_MODE_11G]; } /* Use the first valid TX antenna. */ txant = IWN_LSB(sc->txchainmask); - tx->rflags |= IWN_RFLAG_ANT(txant); + tx->rate |= htole32(IWN_RFLAG_ANT(txant)); essid = (struct iwn_scan_essid *)(tx + 1); if (ss->ss_ssid[0].len != 0) { Modified: head/sys/dev/iwn/if_iwnreg.h ============================================================================== --- head/sys/dev/iwn/if_iwnreg.h Sun May 8 11:42:51 2011 (r221647) +++ head/sys/dev/iwn/if_iwnreg.h Sun May 8 11:49:50 2011 (r221648) @@ -625,8 +625,8 @@ struct iwn4965_node_info { uint32_t reserved7; } __packed; -#define IWN_RFLAG_CCK (1 << 1) -#define IWN_RFLAG_ANT(x) ((x) << 6) +#define IWN_RFLAG_CCK (1 << 9) +#define IWN_RFLAG_ANT(x) ((x) << 14) /* Structure for command IWN_CMD_TX_DATA. */ struct iwn_cmd_data { @@ -647,9 +647,7 @@ struct iwn_cmd_data { #define IWN_TX_NEED_PADDING (1 << 20) uint32_t scratch; - uint8_t plcp; - uint8_t rflags; - uint16_t xrflags; + uint32_t rate; uint8_t id; uint8_t security; @@ -690,11 +688,7 @@ struct iwn_cmd_link_quality { uint8_t ampdu_threshold; uint8_t ampdu_max; uint32_t reserved2; - struct { - uint8_t plcp; - uint8_t rflags; - uint16_t xrflags; - } __packed retry[IWN_MAX_TX_RETRIES]; + uint32_t retry[IWN_MAX_TX_RETRIES]; uint32_t reserved3; } __packed; @@ -1065,9 +1059,7 @@ struct iwn4965_tx_stat { uint8_t btkillcnt; uint8_t rtsfailcnt; uint8_t ackfailcnt; - uint8_t rate; - uint8_t rflags; - uint16_t xrflags; + uint32_t rate; uint16_t duration; uint16_t reserved; uint32_t power[2]; @@ -1079,9 +1071,7 @@ struct iwn5000_tx_stat { uint8_t btkillcnt; uint8_t rtsfailcnt; uint8_t ackfailcnt; - uint8_t rate; - uint8_t rflags; - uint16_t xrflags; + uint32_t rate; uint16_t duration; uint16_t reserved; uint32_t power[2]; @@ -1136,9 +1126,7 @@ struct iwn_rx_stat { uint16_t chan; uint8_t phybuf[32]; - uint8_t rate; - uint8_t rflags; - uint16_t xrflags; + uint32_t rate; uint16_t len; uint16_t reserve3; } __packed; @@ -1534,26 +1522,6 @@ static const struct iwn_chan_band { #define IWN_RIDX_CCK1 0 #define IWN_RIDX_OFDM6 4 -static const struct iwn_rate { - uint8_t rate; - uint8_t plcp; - uint8_t flags; -} iwn_rates[IWN_RIDX_MAX + 1] = { - { 2, 10, IWN_RFLAG_CCK }, - { 4, 20, IWN_RFLAG_CCK }, - { 11, 55, IWN_RFLAG_CCK }, - { 22, 110, IWN_RFLAG_CCK }, - { 12, 0xd, 0 }, - { 18, 0xf, 0 }, - { 24, 0x5, 0 }, - { 36, 0x7, 0 }, - { 48, 0x9, 0 }, - { 72, 0xb, 0 }, - { 96, 0x1, 0 }, - { 108, 0x3, 0 }, - { 120, 0x3, 0 } -}; - #define IWN4965_MAX_PWR_INDEX 107 /* Modified: head/sys/dev/iwn/if_iwnvar.h ============================================================================== --- head/sys/dev/iwn/if_iwnvar.h Sun May 8 11:42:51 2011 (r221647) +++ head/sys/dev/iwn/if_iwnvar.h Sun May 8 11:49:50 2011 (r221648) @@ -101,7 +101,7 @@ struct iwn_node { struct ieee80211_node ni; /* must be the first */ uint16_t disable_tid; uint8_t id; - uint8_t ridx[IEEE80211_RATE_MAXSIZE]; + uint32_t ridx[256]; }; struct iwn_calib_state {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105081149.p48BnoHC044507>