PERFORCE change 137892 for review
Sam Leffler
sam at FreeBSD.org
Mon Mar 17 04:30:51 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=137892
Change 137892 by sam at sam_ebb on 2008/03/17 04:29:52
o implement protection
o use common phy routines
Note: untested
Affected files ...
.. //depot/projects/vap/sys/dev/ral/rt2560.c#19 edit
.. //depot/projects/vap/sys/dev/ral/rt2560var.h#11 edit
Differences ...
==== //depot/projects/vap/sys/dev/ral/rt2560.c#19 (text) ====
@@ -120,11 +120,9 @@
static void rt2560_beacon_update(struct ieee80211vap *, int item);
static void rt2560_beacon_expire(struct rt2560_softc *);
static void rt2560_wakeup_expire(struct rt2560_softc *);
-static uint8_t rt2560_rxrate(struct rt2560_rx_desc *);
static void rt2560_scan_start(struct ieee80211com *);
static void rt2560_scan_end(struct ieee80211com *);
static void rt2560_set_channel(struct ieee80211com *);
-static uint8_t rt2560_plcp_signal(int);
static void rt2560_setup_tx_desc(struct rt2560_softc *,
struct rt2560_tx_desc *, uint32_t, int, int, int,
bus_addr_t);
@@ -132,8 +130,6 @@
struct ieee80211_node *);
static int rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *,
struct ieee80211_node *);
-static struct mbuf *rt2560_get_rts(struct rt2560_softc *,
- struct ieee80211_frame *, uint16_t);
static int rt2560_tx_data(struct rt2560_softc *, struct mbuf *,
struct ieee80211_node *);
static void rt2560_start(struct ifnet *);
@@ -1272,7 +1268,8 @@
tap->wr_tsf =
htole64(((uint64_t)tsf_hi << 32) | tsf_lo);
tap->wr_flags = 0;
- tap->wr_rate = rt2560_rxrate(desc);
+ tap->wr_rate = ieee80211_plcp2rate(desc->rate,
+ le32toh(desc->flags) & RT2560_RX_OFDM);
tap->wr_antenna = sc->rx_ant;
tap->wr_antsignal = RT2560_RSSI(sc, desc->rssi);
@@ -1466,62 +1463,6 @@
#define RT2560_TXRX_TURNAROUND 10 /* us */
-/*
- * This function is only used by the Rx radiotap code.
- */
-static uint8_t
-rt2560_rxrate(struct rt2560_rx_desc *desc)
-{
- if (le32toh(desc->flags) & RT2560_RX_OFDM) {
- /* reverse function of rt2560_plcp_signal */
- switch (desc->rate) {
- 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 */
-}
-
-static uint8_t
-rt2560_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
rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc,
uint32_t flags, int len, int rate, int encrypt, bus_addr_t physaddr)
@@ -1540,11 +1481,11 @@
RT2560_LOGCWMAX(8));
/* setup PLCP fields */
- desc->plcp_signal = rt2560_plcp_signal(rate);
+ desc->plcp_signal = ieee80211_rate2plcp(rate);
desc->plcp_service = 4;
len += IEEE80211_CRC_LEN;
- if (ieee80211_rate2phytype(sc->sc_currates, rate) == IEEE80211_T_OFDM) {
+ if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) {
desc->flags |= htole32(RT2560_TX_OFDM);
plcp_length = len & 0xfff;
@@ -1689,7 +1630,7 @@
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RT2560_TX_ACK;
- dur = ieee80211_ack_duration(sc->sc_currates,
+ dur = ieee80211_ack_duration(sc->sc_rates,
rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
@@ -1720,6 +1661,75 @@
}
static int
+rt2560_sendprot(struct rt2560_softc *sc,
+ const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate)
+{
+ struct ieee80211com *ic = ni->ni_ic;
+ const struct ieee80211_frame *wh;
+ struct rt2560_tx_desc *desc;
+ struct rt2560_tx_data *data;
+ struct mbuf *mprot;
+ int protrate, ackrate, pktlen, flags, isshort, error;
+ uint16_t dur;
+ bus_dma_segment_t segs[RT2560_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 = RT2560_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 |= RT2560_TX_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;
+ }
+
+ desc = &sc->txq.desc[sc->txq.cur_encrypt];
+ data = &sc->txq.data[sc->txq.cur_encrypt];
+
+ error = bus_dmamap_load_mbuf_sg(sc->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;
+ }
+
+ data->m = mprot;
+ data->ni = ieee80211_ref_node(ni);
+ /* ctl frames are not taken into account for rssadapt */
+ data->rix = IEEE80211_FIXED_RATE_NONE;
+
+ rt2560_setup_tx_desc(sc, desc, flags, mprot->m_pkthdr.len, protrate, 1,
+ segs->ds_addr);
+
+ bus_dmamap_sync(sc->txq.data_dmat, data->map,
+ BUS_DMASYNC_PREWRITE);
+
+ sc->txq.queued++;
+ sc->txq.cur_encrypt = (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT;
+
+ return 0;
+}
+
+static int
rt2560_tx_raw(struct rt2560_softc *sc, struct mbuf *m0,
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
{
@@ -1742,6 +1752,21 @@
return EINVAL;
}
+ flags = 0;
+ if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0)
+ flags |= RT2560_TX_ACK;
+ if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) {
+ error = rt2560_sendprot(sc, m0, ni,
+ params->ibp_flags & IEEE80211_BPF_RTS ?
+ IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY,
+ rate);
+ if (error) {
+ m_freem(m0);
+ return error;
+ }
+ flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS;
+ }
+
error = bus_dmamap_load_mbuf_sg(sc->prioq.data_dmat, data->map, m0,
segs, &nsegs, 0);
if (error != 0) {
@@ -1766,10 +1791,6 @@
data->m = m0;
data->ni = ni;
- flags = 0;
- if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0)
- flags |= RT2560_TX_ACK;
-
/* XXX need to setup descriptor ourself */
rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len,
rate, (params->ibp_flags & IEEE80211_BPF_CRYPTO) != 0,
@@ -1790,37 +1811,6 @@
return 0;
}
-/*
- * Build a RTS control frame.
- */
-static struct mbuf *
-rt2560_get_rts(struct rt2560_softc *sc, struct ieee80211_frame *wh,
- uint16_t dur)
-{
- struct ieee80211_frame_rts *rts;
- struct mbuf *m;
-
- 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;
- }
-
- rts = mtod(m, struct ieee80211_frame_rts *);
-
- 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);
-
- m->m_pkthdr.len = m->m_len = sizeof (struct ieee80211_frame_rts);
-
- return m;
-}
-
static int
rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
struct ieee80211_node *ni)
@@ -1837,7 +1827,7 @@
struct mbuf *mnew;
bus_dma_segment_t segs[RT2560_MAX_SCATTER];
uint16_t dur;
- uint32_t flags = 0;
+ uint32_t flags;
int nsegs, rate, error;
wh = mtod(m0, struct ieee80211_frame *);
@@ -1871,68 +1861,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;
-
- rtsrate = ieee80211_ack_rate(sc->sc_currates, rate);
- dur = ieee80211_compute_duration(sc->sc_currates,
- m0->m_pkthdr.len + IEEE80211_CRC_LEN,
- rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
- /* NB: assumes ACK and CTS are the same size */
- dur += ieee80211_ack_duration(sc->sc_currates,
- rtsrate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
- dur += ieee80211_ack_duration(sc->sc_currates,
- rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
-
- m = rt2560_get_rts(sc, wh, dur);
-
- desc = &sc->txq.desc[sc->txq.cur_encrypt];
- data = &sc->txq.data[sc->txq.cur_encrypt];
-
- error = bus_dmamap_load_mbuf_sg(sc->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 = rt2560_sendprot(sc, m0, ni, prot, rate);
+ if (error) {
+ m_freem(m0);
+ return error;
+ }
+ flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS;
}
-
- /* 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;
-
- rt2560_setup_tx_desc(sc, desc, RT2560_TX_ACK |
- RT2560_TX_MORE_FRAG, m->m_pkthdr.len, rtsrate, 1,
- segs->ds_addr);
-
- bus_dmamap_sync(sc->txq.data_dmat, data->map,
- BUS_DMASYNC_PREWRITE);
-
- sc->txq.queued++;
- sc->txq.cur_encrypt =
- (sc->txq.cur_encrypt + 1) % RT2560_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 |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS;
}
data = &sc->txq.data[sc->txq.cur_encrypt];
@@ -1993,7 +1937,7 @@
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RT2560_TX_ACK;
- dur = ieee80211_ack_duration(sc->sc_currates,
+ dur = ieee80211_ack_duration(sc->sc_rates,
rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
}
@@ -2025,12 +1969,6 @@
RAL_LOCK(sc);
- /* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- RAL_UNLOCK(sc);
- return;
- }
-
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
@@ -2207,7 +2145,7 @@
chan = ieee80211_chan2ieee(ic, c);
KASSERT(chan != 0 && chan != IEEE80211_CHAN_ANY, ("chan 0x%x", chan));
- sc->sc_currates = ieee80211_get_ratetable(c);
+ sc->sc_rates = ieee80211_get_ratetable(c);
if (IEEE80211_IS_CHAN_2GHZ(c))
power = min(sc->txpow[chan - 1], 31);
==== //depot/projects/vap/sys/dev/ral/rt2560var.h#11 (text) ====
@@ -125,7 +125,7 @@
int sc_invalid;
int sc_debug;
- const struct ieee80211_rate_table *sc_currates;
+ const struct ieee80211_rate_table *sc_rates;
/*
* The same in both up to here
* ------------------------------------------------
More information about the p4-projects
mailing list