svn commit: r221648 - head/sys/dev/iwn
Bernhard Schmidt
bschmidt at FreeBSD.org
Sun May 8 11:49:51 UTC 2011
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 {
More information about the svn-src-all
mailing list