summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ic/ral.c214
-rw-r--r--sys/dev/ic/ralreg.h5
2 files changed, 84 insertions, 135 deletions
diff --git a/sys/dev/ic/ral.c b/sys/dev/ic/ral.c
index 41ef378b4fc..9af73f39201 100644
--- a/sys/dev/ic/ral.c
+++ b/sys/dev/ic/ral.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ral.c,v 1.31 2005/03/11 20:41:06 damien Exp $ */
+/* $OpenBSD: ral.c,v 1.32 2005/03/11 20:47:59 damien Exp $ */
/*-
* Copyright (c) 2005
@@ -373,8 +373,8 @@ ral_attach(struct ral_softc *sc)
/* set device capabilities */
ic->ic_caps = IEEE80211_C_MONITOR | IEEE80211_C_IBSS |
- IEEE80211_C_SHPREAMBLE | IEEE80211_C_PMGT | IEEE80211_C_TXPMGT |
- IEEE80211_C_WEP;
+ IEEE80211_C_HOSTAP | IEEE80211_C_SHPREAMBLE | IEEE80211_C_PMGT |
+ IEEE80211_C_TXPMGT | IEEE80211_C_WEP;
if (sc->rf_rev == RAL_RF_5222) {
/* set supported .11a rates */
@@ -1060,22 +1060,24 @@ ral_tx_intr(struct ral_softc *sc)
switch (letoh32(desc->flags) & RAL_TX_RESULT_MASK) {
case RAL_TX_SUCCESS:
DPRINTFN(10, ("data frame sent successfully\n"));
- ieee80211_rssadapt_raise_rate(ic, &rn->rssadapt,
- &data->id);
+ if (data->id.id_node != NULL) {
+ ieee80211_rssadapt_raise_rate(ic,
+ &rn->rssadapt, &data->id);
+ }
break;
case RAL_TX_SUCCESS_RETRY:
DPRINTFN(9, ("data frame sent after %u retries\n",
(letoh32(desc->flags) >> 5) & 0x7));
- ieee80211_rssadapt_lower_rate(ic, data->ni,
- &rn->rssadapt, &data->id);
break;
case RAL_TX_FAIL_RETRY:
DPRINTFN(9, ("sending data frame failed (too much "
"retries)\n"));
- ieee80211_rssadapt_lower_rate(ic, data->ni,
- &rn->rssadapt, &data->id);
+ if (data->id.id_node != NULL) {
+ ieee80211_rssadapt_lower_rate(ic, data->ni,
+ &rn->rssadapt, &data->id);
+ }
break;
case RAL_TX_FAIL_INVALID:
@@ -1598,30 +1600,15 @@ ral_setup_tx_desc(struct ral_softc *sc, struct ral_tx_desc *desc,
int
ral_tx_bcn(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ifnet *ifp = &ic->ic_if;
struct ral_tx_desc *desc;
struct ral_tx_data *data;
- struct ieee80211_frame *wh;
- struct ieee80211_duration d0, dn;
- int rate, npkt, error;
+ int rate, error;
desc = &sc->bcnq.desc[sc->bcnq.cur];
data = &sc->bcnq.data[sc->bcnq.cur];
- wh = mtod(m0, struct ieee80211_frame *);
-
rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 4;
- error = ieee80211_compute_duration(wh, m0->m_pkthdr.len,
- ic->ic_flags & ~IEEE80211_F_WEPON, ic->ic_fragthreshold, rate, &d0,
- &dn, &npkt, ifp->if_flags & IFF_DEBUG);
- if (error != 0) {
- printf("%s: could not compute duration\n", sc->sc_dev.dv_xname);
- m_freem(m0);
- return error;
- }
-
error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
BUS_DMA_NOWAIT);
if (error != 0) {
@@ -1634,22 +1621,9 @@ ral_tx_bcn(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
data->m = m0;
data->ni = ni;
- desc->physaddr = htole32(data->map->dm_segs->ds_addr);
-
- desc->flags = htole32(RAL_TX_VALID | RAL_TX_BUSY |
- RAL_TX_INSERT_TIMESTAMP | RAL_TX_IFS_NEW_BACKOFF);
- desc->flags |= htole32(m0->m_pkthdr.len << 16);
-
- desc->wme = htole32(
- 8 << RAL_WME_CWMAX_BITS_SHIFT |
- 3 << RAL_WME_CWMIN_BITS_SHIFT |
- 2 << RAL_WME_AIFSN_BITS_SHIFT);
-
- desc->plcp_length = htole16(d0.d_plcp_len);
- desc->plcp_service = 4;
- desc->plcp_signal = ral_plcp_signal(rate);
- if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
- desc->plcp_signal |= 0x8;
+ ral_setup_tx_desc(sc, desc, RAL_TX_IFS_NEW_BACKOFF |
+ RAL_TX_INSERT_TIMESTAMP, m0->m_pkthdr.len, rate, 0,
+ data->map->dm_segs->ds_addr);
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
@@ -1657,8 +1631,6 @@ ral_tx_bcn(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
sc->bcnq.cur * RAL_TX_DESC_SIZE, RAL_TX_DESC_SIZE,
BUS_DMASYNC_PREWRITE);
- sc->bcnq.cur = (sc->bcnq.cur + 1) % RAL_BEACON_RING_COUNT;
-
return 0;
}
@@ -1666,29 +1638,18 @@ int
ral_tx_mgt(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211com *ic = &sc->sc_ic;
- struct ifnet *ifp = &ic->ic_if;
struct ral_tx_desc *desc;
struct ral_tx_data *data;
struct ieee80211_frame *wh;
- struct ieee80211_duration d0, dn;
- int rate, npkt, error;
+ uint16_t dur;
+ uint32_t flags = 0;
+ int rate, error;
desc = &sc->prioq.desc[sc->prioq.cur];
data = &sc->prioq.data[sc->prioq.cur];
- wh = mtod(m0, struct ieee80211_frame *);
-
rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 4;
- error = ieee80211_compute_duration(wh, m0->m_pkthdr.len,
- ic->ic_flags & ~IEEE80211_F_WEPON, ic->ic_fragthreshold, rate, &d0,
- &dn, &npkt, ifp->if_flags & IFF_DEBUG);
- if (error != 0) {
- printf("%s: could not compute duration\n", sc->sc_dev.dv_xname);
- m_freem(m0);
- return error;
- }
-
error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
BUS_DMA_NOWAIT);
if (error != 0) {
@@ -1721,33 +1682,24 @@ ral_tx_mgt(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
data->m = m0;
data->ni = ni;
- desc->physaddr = htole32(data->map->dm_segs->ds_addr);
-
- desc->flags = htole32(RAL_TX_VALID | RAL_TX_BUSY);
- desc->flags |= htole32(m0->m_pkthdr.len << 16);
+ wh = mtod(m0, struct ieee80211_frame *);
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
- desc->flags |= htole32(RAL_TX_NEED_ACK);
+ flags |= RAL_TX_NEED_ACK;
- *(uint16_t *)wh->i_dur = htole16(d0.d_data_dur);
+ dur = ral_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) + RAL_SIFS;
+ *(uint16_t *)wh->i_dur = htole16(dur);
+ /* tell hardware to add timestamp for probe responses */
if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
IEEE80211_FC0_TYPE_MGT &&
(wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
IEEE80211_FC0_SUBTYPE_PROBE_RESP)
- desc->flags |= htole32(RAL_TX_INSERT_TIMESTAMP);
+ flags |= RAL_TX_INSERT_TIMESTAMP;
}
- desc->wme = htole32(
- 8 << RAL_WME_CWMAX_BITS_SHIFT |
- 3 << RAL_WME_CWMIN_BITS_SHIFT |
- 2 << RAL_WME_AIFSN_BITS_SHIFT);
-
- desc->plcp_length = htole16(d0.d_plcp_len);
- desc->plcp_service = 4;
- desc->plcp_signal = ral_plcp_signal(rate);
- if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
- desc->plcp_signal |= 0x8;
+ ral_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 0,
+ data->map->dm_segs->ds_addr);
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
@@ -1755,8 +1707,8 @@ ral_tx_mgt(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
sc->prioq.cur * RAL_TX_DESC_SIZE, RAL_TX_DESC_SIZE,
BUS_DMASYNC_PREWRITE);
- DPRINTFN(10, ("sending mgt frame len=%u idx=%u duration=%u plcp=%u\n",
- m0->m_pkthdr.len, sc->prioq.cur, d0.d_data_dur, d0.d_plcp_len));
+ DPRINTFN(10, ("sending mgt frame len=%u idx=%u rate=%u\n",
+ m0->m_pkthdr.len, sc->prioq.cur, rate));
/* kick prio */
sc->prioq.queued++;
@@ -1806,10 +1758,10 @@ ral_tx_data(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
struct ral_tx_data *data;
struct ral_node *rn;
struct ieee80211_frame *wh;
- struct ieee80211_frame_rts *rts;
- struct ieee80211_duration d0, dn;
- struct mbuf *m, *mnew;
- int rate, npkt, error;
+ struct mbuf *mnew;
+ uint16_t dur;
+ uint32_t flags = 0;
+ int rate, error;
wh = mtod(m0, struct ieee80211_frame *);
@@ -1818,43 +1770,37 @@ ral_tx_data(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
wh, m0->m_pkthdr.len, ic->ic_fixed_rate, NULL, 0);
rate = ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL;
- error = ieee80211_compute_duration(wh, m0->m_pkthdr.len, ic->ic_flags,
- ic->ic_fragthreshold, rate, &d0, &dn, &npkt,
- ifp->if_flags & IFF_DEBUG);
- if (error != 0) {
- printf("%s: could not compute duration\n", sc->sc_dev.dv_xname);
- m_freem(m0);
- return error;
- }
-
if (ic->ic_flags & IEEE80211_F_WEPON) {
m0 = ieee80211_wep_crypt(ifp, m0, 1);
if (m0 == NULL)
return ENOBUFS;
}
- if (m0->m_pkthdr.len > ic->ic_rtsthreshold) {
- desc = &sc->txq.desc[sc->txq.cur_encrypt];
- data = &sc->txq.data[sc->txq.cur_encrypt];
+ /*
+ * 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 > ic->ic_rtsthreshold) {
+ struct mbuf *m;
+ uint16_t dur;
+ int rtsrate, ackrate;
- /* switch to long retry */
- /* switch to frame gap SIFS */
+ rtsrate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 4;
+ ackrate = ral_ack_rate(rate);
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
- printf("%s: could not allocate RTS/CTS frame\n",
- sc->sc_dev.dv_xname);
- return ENOMEM;
- }
+ dur = ral_txtime(m0->m_pkthdr.len + 4, rate, ic->ic_flags) +
+ ral_txtime(RAL_CTS_SIZE, rtsrate, ic->ic_flags) +
+ ral_txtime(RAL_ACK_SIZE, ackrate, ic->ic_flags) +
+ 3 * RAL_SIFS;
- rts = mtod(m, struct ieee80211_frame_rts *);
- rts->i_fc[0] = IEEE80211_FC0_TYPE_CTL |
- IEEE80211_FC0_SUBTYPE_RTS;
- *(uint16_t *)rts->i_dur = htole16(d0.d_rts_dur);
- memcpy(rts->i_ra, wh->i_addr1, IEEE80211_ADDR_LEN);
- memcpy(rts->i_ta, wh->i_addr2, IEEE80211_ADDR_LEN);
+ m = ral_get_rts(sc, wh, dur);
- error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
+ desc = &sc->txq.desc[sc->txq.cur_encrypt];
+ data = &sc->txq.data[sc->txq.cur_encrypt];
+
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
BUS_DMA_NOWAIT);
if (error != 0) {
printf("%s: could not map mbuf (error %d)\n",
@@ -1864,19 +1810,34 @@ ral_tx_data(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return error;
}
+ /* avoid multiple free() of the same node for each fragment */
+ ieee80211_ref_node(ni);
+
data->m = m;
data->ni = ni;
- bus_dmamap_sync(sc->sc_dmat, data->map, 0,
- data->map->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ /* RTS frames are not taken into account for rssadapt */
+ data->id.id_node = NULL;
- desc->flags = htole32(RAL_TX_VALID | RAL_TX_BUSY);
+ ral_setup_tx_desc(sc, desc, RAL_TX_NEED_ACK | RAL_TX_NOT_LAST,
+ m->m_pkthdr.len, rtsrate, 1, data->map->dm_segs->ds_addr);
- desc->physaddr = htole32(data->map->dm_segs->ds_addr);
+ bus_dmamap_sync(sc->sc_dmat, data->map, 0,
+ data->map->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
+ sc->txq.cur_encrypt * RAL_TX_DESC_SIZE, RAL_TX_DESC_SIZE,
+ BUS_DMASYNC_PREWRITE);
sc->txq.queued++;
sc->txq.cur_encrypt =
(sc->txq.cur_encrypt + 1) % RAL_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 |= RAL_TX_LONG_RETRY | RAL_TX_IFS_SIFS;
}
data = &sc->txq.data[sc->txq.cur_encrypt];
@@ -1951,29 +1912,16 @@ ral_tx_data(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
data->id.id_node = ni;
data->id.id_rssi = ni->ni_rssi;
- desc->physaddr = htole32(data->map->dm_segs->ds_addr);
-
- desc->flags = htole32(RAL_TX_CIPHER_BUSY);
- desc->flags |= htole32(m0->m_pkthdr.len << 16);
-
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
- desc->flags |= htole32(RAL_TX_NEED_ACK);
+ flags |= RAL_TX_NEED_ACK;
- *(uint16_t *)wh->i_dur = htole16(d0.d_data_dur);
+ dur = ral_txtime(RAL_ACK_SIZE, ral_ack_rate(rate),
+ ic->ic_flags) + RAL_SIFS;
+ *(uint16_t *)wh->i_dur = htole16(dur);
}
- desc->wme = htole32(
- 8 << RAL_WME_CWMAX_BITS_SHIFT |
- 3 << RAL_WME_CWMIN_BITS_SHIFT |
- 2 << RAL_WME_AIFSN_BITS_SHIFT);
-
- desc->plcp_length = htole16(d0.d_plcp_len);
- desc->plcp_service = 4;
- if (d0.d_residue != 0)
- desc->plcp_service |= RAL_PLCP_LENGEXT;
- desc->plcp_signal = ral_plcp_signal(rate);
- if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
- desc->plcp_signal |= 0x8;
+ ral_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 1,
+ data->map->dm_segs->ds_addr);
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
@@ -1981,9 +1929,8 @@ ral_tx_data(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
sc->txq.cur_encrypt * RAL_TX_DESC_SIZE, RAL_TX_DESC_SIZE,
BUS_DMASYNC_PREWRITE);
- DPRINTFN(10, ("sending data frame len=%u idx=%u phys=%x plcp=%u "
- "residue=%u\n", m0->m_pkthdr.len, sc->txq.cur_encrypt,
- d0.d_data_dur, d0.d_plcp_len, d0.d_residue));
+ DPRINTFN(10, ("sending data frame len=%u idx=%u rate=%u\n",
+ m0->m_pkthdr.len, sc->txq.cur_encrypt, rate));
/* kick encrypt */
sc->txq.queued++;
@@ -2044,6 +1991,7 @@ ral_start(struct ifnet *ifp)
if (ral_tx_data(sc, m0, ni) != 0) {
if (ni != NULL)
ieee80211_release_node(ic, ni);
+ ifp->if_oerrors++;
break;
}
}
diff --git a/sys/dev/ic/ralreg.h b/sys/dev/ic/ralreg.h
index 739d4a28a46..b15333b30a1 100644
--- a/sys/dev/ic/ralreg.h
+++ b/sys/dev/ic/ralreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ralreg.h,v 1.1 2005/02/15 20:51:21 damien Exp $ */
+/* $OpenBSD: ralreg.h,v 1.2 2005/03/11 20:47:59 damien Exp $ */
/*-
* Copyright (c) 2005
@@ -190,6 +190,8 @@ struct ral_tx_desc {
#define RAL_TX_IFS_NEW_BACKOFF (2 << 13)
#define RAL_TX_IFS_NONE (3 << 13)
+#define RAL_TX_LONG_RETRY (1 << 15)
+
#define RAL_TX_CIPHER_MASK 0xe0000000
#define RAL_TX_CIPHER_NONE (0 << 29)
#define RAL_TX_CIPHER_WEP40 (1 << 29)
@@ -240,7 +242,6 @@ struct ral_rx_desc {
uint32_t reserved[2];
} __packed;
-
#define RAL_RF1 0
#define RAL_RF2 2
#define RAL_RF3 1