From owner-p4-projects@FreeBSD.ORG Mon Mar 17 21:44:10 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7FA4410657A1; Mon, 17 Mar 2008 21:44:10 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DE27F106567C for ; Mon, 17 Mar 2008 21:44:09 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id C6EA98FC3E for ; Mon, 17 Mar 2008 21:44:09 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m2HLi92e008426 for ; Mon, 17 Mar 2008 21:44:09 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m2HLi9RM008424 for perforce@freebsd.org; Mon, 17 Mar 2008 21:44:09 GMT (envelope-from sam@freebsd.org) Date: Mon, 17 Mar 2008 21:44:09 GMT Message-Id: <200803172144.m2HLi9RM008424@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Cc: Subject: PERFORCE change 137955 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 17 Mar 2008 21:44:11 -0000 http://perforce.freebsd.org/chv.cgi?CH=137955 Change 137955 by sam@sam_ebb on 2008/03/17 21:44:03 o track rssadapt changes o add protection o use common phy support Affected files ... .. //depot/projects/vap/sys/dev/ral/rt2661.c#17 edit .. //depot/projects/vap/sys/dev/ral/rt2661var.h#9 edit Differences ... ==== //depot/projects/vap/sys/dev/ral/rt2661.c#17 (text) ==== @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -113,18 +114,12 @@ static void rt2661_mcu_beacon_expire(struct rt2661_softc *); static void rt2661_mcu_wakeup(struct rt2661_softc *); static void rt2661_mcu_cmd_intr(struct rt2661_softc *); -static int rt2661_ack_rate(struct ieee80211com *, int); static void rt2661_scan_start(struct ieee80211com *); static void rt2661_scan_end(struct ieee80211com *); static void rt2661_set_channel(struct ieee80211com *); -static uint16_t rt2661_txtime(int, int, uint32_t); -static uint8_t rt2661_rxrate(struct rt2661_rx_desc *); -static uint8_t rt2661_plcp_signal(int); static void rt2661_setup_tx_desc(struct rt2661_softc *, struct rt2661_tx_desc *, uint32_t, uint16_t, int, int, const bus_dma_segment_t *, int, int); -static struct mbuf * rt2661_get_rts(struct rt2661_softc *, - struct ieee80211_frame *, uint16_t); static int rt2661_tx_data(struct rt2661_softc *, struct mbuf *, struct ieee80211_node *, int); static int rt2661_tx_mgt(struct rt2661_softc *, struct mbuf *, @@ -319,6 +314,8 @@ ic->ic_vap_create = rt2661_vap_create; ic->ic_vap_delete = rt2661_vap_delete; + sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); + bpfattach(ifp, DLT_IEEE802_11_RADIO, sizeof (struct ieee80211_frame) + sizeof (sc->sc_txtap)); @@ -430,8 +427,7 @@ vap->iv_update_beacon = rt2661_beacon_update; #endif - callout_init(&rvp->rssadapt_ch, CALLOUT_MPSAFE); - ieee80211_rssadapt_init(&rvp->rssadapt, vap); + ieee80211_rssadapt_init(&rvp->rssadapt, vap, 100 /*ms*/); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); @@ -445,7 +441,7 @@ { struct rt2661_vap *rvp = RT2661_VAP(vap); - callout_stop(&rvp->rssadapt_ch); + ieee80211_rssadapt_cleanup(&rvp->rssadapt); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); } @@ -785,38 +781,7 @@ return (rn != NULL) ? &rn->ni : NULL; } -/* - * This function is called for each node present in the node station table. - */ static void -rt2661_iter_func(void *arg, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = arg; - - if (ni->ni_vap == vap) - ieee80211_rssadapt_updatestats(&RT2661_NODE(ni)->rssadapt); -} - -/* - * This function is called periodically (every 100ms) in RUN state to update - * the rate adaptation statistics. - */ -static void -rt2661_update_rssadapt(void *arg) -{ - struct ieee80211vap *vap = arg; - struct rt2661_vap *rvp = RT2661_VAP(vap); - - if (vap->iv_opmode != IEEE80211_M_STA) { - struct ieee80211com *ic = vap->iv_ic; - ieee80211_iterate_nodes(&ic->ic_sta, rt2661_iter_func, arg); - } else - rt2661_iter_func(arg, vap->iv_bss); - - callout_reset(&rvp->rssadapt_ch, hz / 10, rt2661_update_rssadapt, vap); -} - -static void rt2661_newassoc(struct ieee80211_node *ni, int isnew) { struct ieee80211vap *vap = ni->ni_vap; @@ -836,8 +801,6 @@ if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) { uint32_t tmp; - callout_stop(&rvp->rssadapt_ch); - /* abort TSF synchronization */ tmp = RAL_READ(sc, RT2661_TXRX_CSR9); RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0x00ffffff); @@ -847,7 +810,6 @@ if (error == 0 && nstate == IEEE80211_S_RUN) { struct ieee80211_node *ni = vap->iv_bss; - const struct ieee80211_txparam *tp; if (vap->iv_opmode != IEEE80211_M_MONITOR) { rt2661_enable_mrr(sc); @@ -867,11 +829,6 @@ /* fake a join to init the tx rate */ rt2661_newassoc(ni, 1); } - tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; - if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) - callout_reset(&rvp->rssadapt_ch, hz / 10, - rt2661_update_rssadapt, vap); - rt2661_enable_tsf_sync(sc); } } @@ -970,7 +927,7 @@ if (ni == NULL) continue; - rn = (struct rt2661_node *)ni; + rn = RT2661_NODE(ni); switch (RT2661_TX_RESULT(val)) { case RT2661_TX_SUCCESS: @@ -980,8 +937,9 @@ "%d retries\n", retrycnt); if (retrycnt == 0 && data->rix != IEEE80211_FIXED_RATE_NONE) { - ieee80211_rssadapt_tx_complete(&rn->rssadapt, 1, - m->m_pkthdr.len, data->rix, data->rssi); + ieee80211_rssadapt_tx_complete(&rn->rssadapt, + IEEE80211_RSSADAPT_SUCCESS, + m->m_pkthdr.len, data->rssi); } ifp->if_opackets++; break; @@ -990,8 +948,9 @@ DPRINTFN(sc, 9, "%s\n", "sending data frame failed (too much retries)"); if (data->rix != IEEE80211_FIXED_RATE_NONE) { - ieee80211_rssadapt_tx_complete(&rn->rssadapt, 0, - m->m_pkthdr.len, data->rix, data->rssi); + ieee80211_rssadapt_tx_complete(&rn->rssadapt, + IEEE80211_RSSADAPT_FAILURE, + m->m_pkthdr.len, data->rssi); } ifp->if_oerrors++; break; @@ -1157,7 +1116,8 @@ tap->wr_tsf = htole64(((uint64_t)tsf_hi << 32) | tsf_lo); tap->wr_flags = 0; - tap->wr_rate = rt2661_rxrate(desc); + tap->wr_rate = ieee80211_plcp2rate(desc->rate, + le32toh(desc->flags) & RT2661_RX_OFDM); tap->wr_antsignal = rssi < 0 ? 0 : rssi; bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); @@ -1284,131 +1244,6 @@ RAL_UNLOCK(sc); } -/* quickly determine if a given rate is CCK or OFDM */ -#define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) - -#define RAL_ACK_SIZE 14 /* 10 + 4(FCS) */ -#define RAL_CTS_SIZE 14 /* 10 + 4(FCS) */ - -#define RAL_SIFS 10 /* us */ - -/* - * This function is only used by the Rx radiotap code. It returns the rate at - * which a given frame was received. - */ -static uint8_t -rt2661_rxrate(struct rt2661_rx_desc *desc) -{ - if (le32toh(desc->flags) & RT2661_RX_OFDM) { - /* reverse function of rt2661_plcp_signal */ - switch (desc->rate & 0xf) { - case 0xb: return 12; - case 0xf: return 18; - case 0xa: return 24; - case 0xe: return 36; - case 0x9: return 48; - case 0xd: return 72; - case 0x8: return 96; - case 0xc: return 108; - } - } else { - if (desc->rate == 10) - return 2; - if (desc->rate == 20) - return 4; - if (desc->rate == 55) - return 11; - if (desc->rate == 110) - return 22; - } - return 2; /* should not get there */ -} - -/* - * Return the expected ack rate for a frame transmitted at rate `rate'. - * XXX: this should depend on the destination node basic rate set. - */ -static int -rt2661_ack_rate(struct ieee80211com *ic, int rate) -{ - switch (rate) { - /* CCK rates */ - case 2: - return 2; - case 4: - case 11: - case 22: - return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate; - - /* OFDM rates */ - case 12: - case 18: - return 12; - case 24: - case 36: - return 24; - case 48: - case 72: - case 96: - case 108: - return 48; - } - - /* default to 1Mbps */ - return 2; -} - -/* - * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'. - * The function automatically determines the operating mode depending on the - * given rate. `flags' indicates whether short preamble is in use or not. - */ -static uint16_t -rt2661_txtime(int len, int rate, uint32_t flags) -{ - uint16_t txtime; - - if (RAL_RATE_IS_OFDM(rate)) { - /* IEEE Std 802.11a-1999, pp. 37 */ - txtime = (8 + 4 * len + 3 + rate - 1) / rate; - txtime = 16 + 4 + 4 * txtime + 6; - } else { - /* IEEE Std 802.11b-1999, pp. 28 */ - txtime = (16 * len + rate - 1) / rate; - if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) - txtime += 72 + 24; - else - txtime += 144 + 48; - } - - return txtime; -} - -static uint8_t -rt2661_plcp_signal(int rate) -{ - switch (rate) { - /* CCK rates (returned values are device-dependent) */ - case 2: return 0x0; - case 4: return 0x1; - case 11: return 0x2; - case 22: return 0x3; - - /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ - case 12: return 0xb; - case 18: return 0xf; - case 24: return 0xa; - case 36: return 0xe; - case 48: return 0x9; - case 72: return 0xd; - case 96: return 0x8; - case 108: return 0xc; - - /* unsupported rates (should not get there) */ - default: return 0xff; - } -} - static void rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc, uint32_t flags, uint16_t xflags, int len, int rate, @@ -1439,11 +1274,11 @@ desc->qid = ac; /* setup PLCP fields */ - desc->plcp_signal = rt2661_plcp_signal(rate); + desc->plcp_signal = ieee80211_rate2plcp(rate); desc->plcp_service = 4; len += IEEE80211_CRC_LEN; - if (RAL_RATE_IS_OFDM(rate)) { + if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) { desc->flags |= htole32(RT2661_TX_OFDM); plcp_length = len & 0xfff; @@ -1529,8 +1364,8 @@ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { flags |= RT2661_TX_NEED_ACK; - dur = rt2661_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) + - RAL_SIFS; + dur = ieee80211_ack_duration(sc->sc_rates, + rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE); *(uint16_t *)wh->i_dur = htole16(dur); /* tell hardware to add timestamp in probe responses */ @@ -1558,35 +1393,74 @@ return 0; } -/* - * Build a RTS control frame. - */ -static struct mbuf * -rt2661_get_rts(struct rt2661_softc *sc, struct ieee80211_frame *wh, - uint16_t dur) +static int +rt2661_sendprot(struct rt2661_softc *sc, int ac, + const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate) { - struct ieee80211_frame_rts *rts; - struct mbuf *m; + struct ieee80211com *ic = ni->ni_ic; + struct rt2661_tx_ring *txq = &sc->txq[ac]; + const struct ieee80211_frame *wh; + struct rt2661_tx_desc *desc; + struct rt2661_tx_data *data; + struct mbuf *mprot; + int protrate, ackrate, pktlen, flags, isshort, error; + uint16_t dur; + bus_dma_segment_t segs[RT2661_MAX_SCATTER]; + int nsegs; + + KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY, + ("protection %d", prot)); + + wh = mtod(m, const struct ieee80211_frame *); + pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; + + protrate = ieee80211_ctl_rate(sc->sc_rates, rate); + ackrate = ieee80211_ack_rate(sc->sc_rates, rate); + + isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; + dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort); + + ieee80211_ack_duration(sc->sc_rates, rate, isshort); + flags = RT2661_TX_MORE_FRAG; + if (prot == IEEE80211_PROT_RTSCTS) { + /* NB: CTS is the same size as an ACK */ + dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort); + flags |= RT2661_TX_NEED_ACK; + mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); + } else { + mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); + } + if (mprot == NULL) { + /* XXX stat + msg */ + return ENOBUFS; + } + + data = &txq->data[txq->cur]; + desc = &txq->desc[txq->cur]; - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) { - sc->sc_ic.ic_stats.is_tx_nobuf++; - device_printf(sc->sc_dev, "could not allocate RTS frame\n"); - return NULL; + error = bus_dmamap_load_mbuf_sg(txq->data_dmat, data->map, mprot, segs, + &nsegs, 0); + if (error != 0) { + device_printf(sc->sc_dev, + "could not map mbuf (error %d)\n", error); + m_freem(mprot); + return error; } - rts = mtod(m, struct ieee80211_frame_rts *); + data->m = mprot; + data->ni = ieee80211_ref_node(ni); + /* ctl frames are not taken into account for rssadapt */ + data->rix = IEEE80211_FIXED_RATE_NONE; + + rt2661_setup_tx_desc(sc, desc, flags, 0, mprot->m_pkthdr.len, + protrate, segs, 1, ac); - rts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL | - IEEE80211_FC0_SUBTYPE_RTS; - rts->i_fc[1] = IEEE80211_FC1_DIR_NODS; - *(uint16_t *)rts->i_dur = htole16(dur); - IEEE80211_ADDR_COPY(rts->i_ra, wh->i_addr1); - IEEE80211_ADDR_COPY(rts->i_ta, wh->i_addr2); + bus_dmamap_sync(txq->data_dmat, data->map, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(txq->desc_dmat, txq->desc_map, BUS_DMASYNC_PREWRITE); - m->m_pkthdr.len = m->m_len = sizeof (struct ieee80211_frame_rts); + txq->queued++; + txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT; - return m; + return 0; } static int @@ -1599,7 +1473,6 @@ struct ifnet *ifp = sc->sc_ifp; struct rt2661_tx_desc *desc; struct rt2661_tx_data *data; - struct rt2661_node *rn; struct ieee80211_frame *wh; const struct ieee80211_txparam *tp; struct ieee80211_key *k; @@ -1607,7 +1480,7 @@ struct mbuf *mnew; bus_dma_segment_t segs[RT2661_MAX_SCATTER]; uint16_t dur; - uint32_t flags = 0; + uint32_t flags; int error, nsegs, rate, noack = 0; wh = mtod(m0, struct ieee80211_frame *); @@ -1620,13 +1493,9 @@ } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = tp->ucastrate; } else { - struct ieee80211_rateset *rs; - - rs = &ni->ni_rates; - rn = (struct rt2661_node *)ni; - ni->ni_txrate = ieee80211_rssadapt_choose(&rn->rssadapt, rs, + (void) ieee80211_rssadapt_choose(ni, &RT2661_NODE(ni)->rssadapt, m0->m_pkthdr.len); - rate = rs->rs_rates[ni->ni_txrate]; + rate = ni->ni_txrate; } rate &= IEEE80211_RATE_VAL; @@ -1646,66 +1515,22 @@ wh = mtod(m0, struct ieee80211_frame *); } - /* - * IEEE Std 802.11-1999, pp 82: "A STA shall use an RTS/CTS exchange - * for directed frames only when the length of the MPDU is greater - * than the length threshold indicated by [...]" ic_rtsthreshold. - */ - if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - m0->m_pkthdr.len > vap->iv_rtsthreshold) { - struct mbuf *m; - uint16_t dur; - int rtsrate, ackrate; - - rtsrate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; - ackrate = rt2661_ack_rate(ic, rate); - - dur = rt2661_txtime(m0->m_pkthdr.len + 4, rate, ic->ic_flags) + - rt2661_txtime(RAL_CTS_SIZE, rtsrate, ic->ic_flags) + - /* XXX: noack (QoS)? */ - rt2661_txtime(RAL_ACK_SIZE, ackrate, ic->ic_flags) + - 3 * RAL_SIFS; - - m = rt2661_get_rts(sc, wh, dur); - - desc = &txq->desc[txq->cur]; - data = &txq->data[txq->cur]; - - error = bus_dmamap_load_mbuf_sg(txq->data_dmat, data->map, m, - segs, &nsegs, 0); - if (error != 0) { - device_printf(sc->sc_dev, - "could not map mbuf (error %d)\n", error); - m_freem(m); - m_freem(m0); - return error; + flags = 0; + if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { + int prot = IEEE80211_PROT_NONE; + if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) + prot = IEEE80211_PROT_RTSCTS; + else if ((ic->ic_flags & IEEE80211_F_USEPROT) && + ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) + prot = ic->ic_protmode; + if (prot != IEEE80211_PROT_NONE) { + error = rt2661_sendprot(sc, ac, m0, ni, prot, rate); + if (error) { + m_freem(m0); + return error; + } + flags |= RT2661_TX_LONG_RETRY | RT2661_TX_IFS; } - - /* avoid multiple free() of the same node for each fragment */ - ieee80211_ref_node(ni); - - data->m = m; - data->ni = ni; - - /* RTS frames are not taken into account for rssadapt */ - data->rix = IEEE80211_FIXED_RATE_NONE; - - rt2661_setup_tx_desc(sc, desc, RT2661_TX_NEED_ACK | - RT2661_TX_MORE_FRAG, 0, m->m_pkthdr.len, rtsrate, segs, - nsegs, ac); - - bus_dmamap_sync(txq->data_dmat, data->map, - BUS_DMASYNC_PREWRITE); - - txq->queued++; - txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT; - - /* - * IEEE Std 802.11-1999: when an RTS/CTS exchange is used, the - * asynchronous data frame shall be transmitted after the CTS - * frame and a SIFS period. - */ - flags |= RT2661_TX_LONG_RETRY | RT2661_TX_IFS; } data = &txq->data[txq->cur]; @@ -1767,8 +1592,8 @@ if (!noack && !IEEE80211_IS_MULTICAST(wh->i_addr1)) { flags |= RT2661_TX_NEED_ACK; - dur = rt2661_txtime(RAL_ACK_SIZE, rt2661_ack_rate(ic, rate), - ic->ic_flags) + RAL_SIFS; + dur = ieee80211_ack_duration(sc->sc_rates, + rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE); *(uint16_t *)wh->i_dur = htole16(dur); } @@ -2170,6 +1995,8 @@ chan = ieee80211_chan2ieee(ic, c); KASSERT(chan != 0 && chan != IEEE80211_CHAN_ANY, ("chan 0x%x", chan)); + sc->sc_rates = ieee80211_get_ratetable(c); + /* select the appropriate RF settings based on what EEPROM says */ rfprog = (sc->rfprog == 0) ? rt2661_rf5225_1 : rt2661_rf5225_2; ==== //depot/projects/vap/sys/dev/ral/rt2661var.h#9 (text) ==== @@ -95,7 +95,6 @@ struct rt2661_vap { struct ieee80211vap ral_vap; struct ieee80211_rssadapt rssadapt; - struct callout rssadapt_ch; int (*ral_newstate)(struct ieee80211vap *, enum ieee80211_state, int); @@ -116,6 +115,8 @@ int sc_tx_timer; int sc_invalid; int sc_debug; + + const struct ieee80211_rate_table *sc_rates; /* * The same in both up to here * ------------------------------------------------