PERFORCE change 137955 for review
Sam Leffler
sam at FreeBSD.org
Mon Mar 17 21:44:11 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=137955
Change 137955 by sam at 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 <net/if_types.h>
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_phy.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_rssadapt.h>
@@ -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
* ------------------------------------------------
More information about the p4-projects
mailing list