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 {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to