PERFORCE change 76439 for review
Sam Leffler
sam at FreeBSD.org
Tue May 3 09:28:20 PDT 2005
http://perforce.freebsd.org/chv.cgi?CH=76439
Change 76439 by sam at sam_ebb on 2005/05/03 16:28:08
IFC @ 76395 (remainder)
Affected files ...
.. //depot/projects/vap/sys/dev/an/if_an.c#2 integrate
.. //depot/projects/vap/sys/dev/an/if_an_pci.c#2 integrate
.. //depot/projects/vap/sys/dev/ath/ath_rate/amrr/amrr.c#2 integrate
.. //depot/projects/vap/sys/dev/ath/ath_rate/onoe/onoe.c#4 integrate
.. //depot/projects/vap/sys/dev/ath/ath_rate/sample/sample.c#1 add
.. //depot/projects/vap/sys/dev/ath/ath_rate/sample/sample.h#1 add
.. //depot/projects/vap/sys/dev/ath/if_ath.c#6 edit
.. //depot/projects/vap/sys/dev/ath/if_ath_pci.c#2 integrate
.. //depot/projects/vap/sys/dev/ath/if_athioctl.h#2 integrate
.. //depot/projects/vap/sys/dev/ath/if_athrate.h#3 integrate
.. //depot/projects/vap/sys/dev/ath/if_athvar.h#4 integrate
.. //depot/projects/vap/sys/dev/awi/awi.c#2 integrate
.. //depot/projects/vap/sys/dev/ipw/if_ipw.c#1 branch
.. //depot/projects/vap/sys/dev/ipw/if_ipwreg.h#1 branch
.. //depot/projects/vap/sys/dev/ipw/if_ipwvar.h#1 branch
.. //depot/projects/vap/sys/dev/iwi/if_iwi.c#4 integrate
.. //depot/projects/vap/sys/dev/iwi/if_iwireg.h#2 integrate
.. //depot/projects/vap/sys/dev/iwi/if_iwivar.h#3 integrate
.. //depot/projects/vap/sys/net80211/_ieee80211.h#3 integrate
.. //depot/projects/vap/sys/net80211/ieee80211.c#6 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_crypto.c#3 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_crypto.h#4 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_crypto_ccmp.c#3 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_crypto_none.c#3 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_crypto_tkip.c#3 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_crypto_wep.c#3 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_freebsd.c#6 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_freebsd.h#4 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_input.c#7 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_ioctl.c#5 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_ioctl.h#4 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_node.c#4 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_node.h#4 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_output.c#6 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_proto.c#5 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_proto.h#4 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_radiotap.h#2 integrate
.. //depot/projects/vap/sys/net80211/ieee80211_var.h#7 integrate
.. //depot/projects/vap/tools/tools/ath/80211stats.c#3 integrate
.. //depot/projects/vap/tools/tools/ath/80211watch.c#2 integrate
.. //depot/projects/vap/tools/tools/ath/athstats.c#3 integrate
Differences ...
==== //depot/projects/vap/sys/dev/an/if_an.c#2 (text+ko) ====
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/an/if_an.c,v 1.64 2005/01/06 01:42:28 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/an/if_an.c,v 1.65 2005/03/28 17:52:12 sam Exp $");
/*
* The Aironet 4500/4800 series cards come in PCMCIA, ISA and PCI form.
@@ -2011,7 +2011,9 @@
case SIOCGPRIVATE_0: /* used by Cisco client utility */
if ((error = suser(td)))
goto out;
- copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
+ error = copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
+ if (error)
+ goto out;
mode = l_ioctl.command;
if (mode >= AIROGCAP && mode <= AIROGSTATSD32) {
@@ -2023,18 +2025,20 @@
} else {
error =-1;
}
-
- /* copy out the updated command info */
- copyout(&l_ioctl, ifr->ifr_data, sizeof(l_ioctl));
-
+ if (!error) {
+ /* copy out the updated command info */
+ error = copyout(&l_ioctl, ifr->ifr_data, sizeof(l_ioctl));
+ }
break;
case SIOCGPRIVATE_1: /* used by Cisco client utility */
if ((error = suser(td)))
goto out;
- copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
+ error = copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
+ if (error)
+ goto out;
l_ioctl.command = 0;
error = AIROMAGIC;
- copyout(&error, l_ioctl.data, sizeof(error));
+ (void) copyout(&error, l_ioctl.data, sizeof(error));
error = 0;
break;
case SIOCG80211:
@@ -3376,9 +3380,10 @@
sc->areq.an_type = rid;
/* Just copy the data back */
- copyin((l_ioctl->data) + 2, &sc->areq.an_val,
- l_ioctl->len);
-
+ if (copyin((l_ioctl->data) + 2, &sc->areq.an_val,
+ l_ioctl->len)) {
+ return -EFAULT;
+ }
an_cmd(sc, AN_CMD_DISABLE, 0);
an_write_record(sc, (struct an_ltv_gen *)&sc->areq);
an_cmd(sc, AN_CMD_ENABLE, 0);
@@ -3689,15 +3694,18 @@
return ENOBUFS;
break;
case AIROFLSHGCHR: /* Get char from aux */
- copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
+ status = copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
+ if (status)
+ return status;
z = *(int *)&sc->areq;
if ((status = flashgchar(ifp, z, 8000)) == 1)
return 0;
else
return -1;
- break;
case AIROFLSHPCHR: /* Send char to card. */
- copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
+ status = copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
+ if (status)
+ return status;
z = *(int *)&sc->areq;
if ((status = flashpchar(ifp, z, 8000)) == -1)
return -EIO;
@@ -3710,7 +3718,9 @@
l_ioctl->len, FLASH_SIZE);
return -EINVAL;
}
- copyin(l_ioctl->data, sc->an_flash_buffer, l_ioctl->len);
+ status = copyin(l_ioctl->data, sc->an_flash_buffer, l_ioctl->len);
+ if (status)
+ return status;
if ((status = flashputbuf(ifp)) != 0)
return -EIO;
==== //depot/projects/vap/sys/dev/an/if_an_pci.c#2 (text+ko) ====
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/an/if_an_pci.c,v 1.26 2003/12/30 01:07:12 ambrisko Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/an/if_an_pci.c,v 1.27 2005/03/05 19:06:11 imp Exp $");
/*
* This is a PCI shim for the Aironet PC4500/4800 wireless network
@@ -125,7 +125,7 @@
if (pci_get_vendor(dev) == t->an_vid &&
pci_get_device(dev) == t->an_did) {
device_set_desc(dev, t->an_name);
- return(0);
+ return(BUS_PROBE_DEFAULT);
}
t++;
}
@@ -133,7 +133,7 @@
if (pci_get_vendor(dev) == AIRONET_VENDORID &&
pci_get_device(dev) == AIRONET_DEVICEID_MPI350) {
device_set_desc(dev, "Cisco Aironet MPI350");
- return(0);
+ return(BUS_PROBE_DEFAULT);
}
return(ENXIO);
==== //depot/projects/vap/sys/dev/ath/ath_rate/amrr/amrr.c#2 (text+ko) ====
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/amrr/amrr.c,v 1.3 2004/12/31 22:41:45 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/amrr/amrr.c,v 1.7 2005/04/02 18:54:30 sam Exp $");
/*
* AMRR rate control. See:
@@ -114,7 +114,7 @@
void
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
- HAL_BOOL shortPreamble, size_t frameLen,
+ int shortPreamble, size_t frameLen,
u_int8_t *rix, int *try0, u_int8_t *txrate)
{
struct amrr_node *amn = ATH_NODE_AMRR(an);
@@ -129,7 +129,7 @@
void
ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
- struct ath_desc *ds, HAL_BOOL shortPreamble, u_int8_t rix)
+ struct ath_desc *ds, int shortPreamble, u_int8_t rix)
{
struct amrr_node *amn = ATH_NODE_AMRR(an);
@@ -141,8 +141,8 @@
}
void
-ath_rate_tx_complete(struct ath_softc *sc,
- struct ath_node *an, const struct ath_desc *ds)
+ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
+ const struct ath_desc *ds, const struct ath_desc *ds0)
{
struct amrr_node *amn = ATH_NODE_AMRR(an);
int sr = ds->ds_txstat.ts_shortretry;
@@ -326,7 +326,9 @@
static void
ath_rate_cb(void *arg, struct ieee80211_node *ni)
{
- ath_rate_update(ni->ni_ic->ic_ifp->if_softc, ni, (int)(uintptr_t) arg);
+ struct ath_softc *sc = arg;
+
+ ath_rate_update(sc, ni, 0);
}
/*
@@ -361,7 +363,7 @@
* For any other operating mode we want to reset the
* tx rate state of each node.
*/
- ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, 0);
+ ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, sc);
ath_rate_update(sc, ic->ic_bss, 0);
}
if (ic->ic_fixed_rate == -1 && state == IEEE80211_S_RUN) {
==== //depot/projects/vap/sys/dev/ath/ath_rate/onoe/onoe.c#4 (text+ko) ====
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/onoe/onoe.c,v 1.3 2004/12/31 22:41:45 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/onoe/onoe.c,v 1.7 2005/04/02 18:54:30 sam Exp $");
/*
* Atsushi Onoe's rate control algorithm.
@@ -130,7 +130,7 @@
void
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
- HAL_BOOL shortPreamble, size_t frameLen,
+ int shortPreamble, size_t frameLen,
u_int8_t *rix, int *try0, u_int8_t *txrate)
{
struct onoe_node *on = ATH_NODE_ONOE(an);
@@ -145,7 +145,7 @@
void
ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
- struct ath_desc *ds, HAL_BOOL shortPreamble, u_int8_t rix)
+ struct ath_desc *ds, int shortPreamble, u_int8_t rix)
{
struct onoe_node *on = ATH_NODE_ONOE(an);
@@ -157,8 +157,8 @@
}
void
-ath_rate_tx_complete(struct ath_softc *sc,
- struct ath_node *an, const struct ath_desc *ds)
+ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
+ const struct ath_desc *ds, const struct ath_desc *ds0)
{
struct onoe_node *on = ATH_NODE_ONOE(an);
@@ -315,7 +315,9 @@
static void
ath_rate_cb(void *arg, struct ieee80211_node *ni)
{
- ath_rate_update(ni->ni_ic->ic_ifp->if_softc, ni, (int)(uintptr_t) arg);
+ struct ath_softc *sc = arg;
+
+ ath_rate_update(sc, ni, 0);
}
/*
@@ -343,7 +345,7 @@
/*
* Reset the tx rate state of each station/neighbor.
*/
- ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, 0);
+ ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, sc);
ath_rate_update(sc, vap->iv_bss, 0);
}
}
==== //depot/projects/vap/sys/dev/ath/if_ath.c#6 (text+ko) ====
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath.c,v 1.66 2004/12/31 22:41:45 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath.c,v 1.88 2005/04/12 17:56:43 sam Exp $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -1792,6 +1792,35 @@
struct ath_softc *sc = ic->ic_ifp->if_softc;
/*
+ * Group key allocation must be handled specially for
+ * parts that do not support multicast key cache search
+ * functionality. For those parts the key id must match
+ * the h/w key index so lookups find the right key. On
+ * parts w/ the key search facility we install the sender's
+ * mac address (with the high bit set) and let the hardware
+ * find the key w/o using the key id. This is preferred as
+ * it permits us to support multiple users for adhoc and/or
+ * multi-station operation.
+ */
+ if ((k->wk_flags & IEEE80211_KEY_GROUP) && !sc->sc_mcastkey) {
+ u_int keyix;
+
+ if (!(&vap->iv_nw_keys[0] <= k &&
+ k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) {
+ /* should not happen */
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE,
+ "%s: bogus group key\n", __func__);
+ return IEEE80211_KEYIX_NONE;
+ }
+ keyix = k - vap->iv_nw_keys;
+ /*
+ * XXX we pre-allocate the global keys so
+ * have no way to check if they've already been allocated.
+ */
+ return keyix;
+ }
+
+ /*
* We allocate two pair for TKIP when using the h/w to do
* the MIC. For everything else, including software crypto,
* we allocate a single entry. Note that s/w crypto requires
@@ -1981,18 +2010,6 @@
__func__, rfilt, mfilt[0], mfilt[1]);
}
-static void
-ath_mbuf_load_cb(void *arg, bus_dma_segment_t *seg, int nseg, bus_size_t mapsize, int error)
-{
- struct ath_buf *bf = arg;
-
- KASSERT(nseg <= ATH_MAX_SCATTER, ("too many DMA segments %u", nseg));
- KASSERT(error == 0, ("error %u on bus_dma callback", error));
- bf->bf_mapsize = mapsize;
- bf->bf_nseg = nseg;
- bcopy(seg, bf->bf_segs, nseg * sizeof (seg[0]));
-}
-
/*
* Set the slot time based on the current setting.
*/
@@ -2074,8 +2091,8 @@
sc->sc_stats.ast_be_nombuf++;
return ENOMEM;
}
- error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m,
- ath_mbuf_load_cb, bf,
+ error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
+ bf->bf_segs, &bf->bf_nseg,
BUS_DMA_NOWAIT);
if (error == 0) {
bf->bf_m = m;
@@ -2220,12 +2237,12 @@
if (ieee80211_beacon_update(ni, &sc->sc_boff, m, ncabq)) {
/* XXX too conservative? */
bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
- error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m,
- ath_mbuf_load_cb, bf,
+ error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
+ bf->bf_segs, &bf->bf_nseg,
BUS_DMA_NOWAIT);
if (error != 0) {
if_printf(ic->ic_ifp,
- "%s: bus_dmamap_load_mbuf failed, error %u\n",
+ "%s: bus_dmamap_load_mbuf_sg failed, error %u\n",
__func__, error);
return;
}
@@ -2340,7 +2357,6 @@
static void
ath_beacon_config(struct ath_softc *sc)
{
-#define MS_TO_TU(x) (((x) * 1000) / 1024)
struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); /*XXX*/
@@ -2395,7 +2411,8 @@
*
* XXX fixed at 100ms
*/
- bs.bs_sleepduration = roundup(MS_TO_TU(100), bs.bs_intval);
+ bs.bs_sleepduration =
+ roundup(IEEE80211_MS_TO_TU(100), bs.bs_intval);
if (bs.bs_sleepduration > bs.bs_dtimperiod)
bs.bs_sleepduration = roundup(bs.bs_sleepduration, bs.bs_dtimperiod);
@@ -2450,7 +2467,6 @@
if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol)
ath_beacon_proc(sc, 0);
}
-#undef MS_TO_TU
}
static void
@@ -2726,14 +2742,14 @@
bf->bf_m = m;
m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
- error = bus_dmamap_load_mbuf(sc->sc_dmat,
+ error = bus_dmamap_load_mbuf_sg(sc->sc_dmat,
bf->bf_dmamap, m,
- ath_mbuf_load_cb, bf,
+ bf->bf_segs, &bf->bf_nseg,
BUS_DMA_NOWAIT);
if (error != 0) {
DPRINTF(sc, ATH_DEBUG_ANY,
- "%s: bus_dmamap_load_mbuf failed; error %d\n",
- __func__, error);
+ "%s: bus_dmamap_load_mbuf_sg failed; error %d\n",
+ __func__, error);
sc->sc_stats.ast_rx_busdma++;
return error;
}
@@ -2772,6 +2788,21 @@
}
/*
+ * Extend 15-bit time stamp from rx descriptor to
+ * a full 64-bit TSF using the current h/w TSF.
+ */
+static __inline u_int64_t
+ath_extend_tsf(struct ath_hal *ah, u_int32_t rstamp)
+{
+ u_int64_t tsf;
+
+ tsf = ath_hal_gettsf64(ah);
+ if ((tsf & 0x7fff) < rstamp)
+ tsf -= 0x8000;
+ return ((tsf &~ 0x7fff) | rstamp);
+}
+
+/*
* Intercept management frames to collect beacon rssi data
* and to do ibss merges.
*/
@@ -2796,10 +2827,7 @@
vap = ni->ni_vap;
if (vap->iv_opmode == IEEE80211_M_IBSS &&
vap->iv_state == IEEE80211_S_RUN) {
- struct ath_hal *ah = sc->sc_ah;
- /* XXX extend rstamp */
- u_int64_t tsf = ath_hal_gettsf64(ah);
-
+ u_int64_t tsf = ath_extend_tsf(sc->sc_ah, rstamp);
/*
* Handle ibss merge as needed; check the tsf on the
* frame before attempting the merge. The 802.11 spec
@@ -2807,11 +2835,16 @@
* the oldest station with the same ssid, where oldest
* is determined by the tsf. Note that hardware
* reconfiguration happens through callback to
- * ath_newstate as the state machine will be go
- * from RUN -> RUN when this happens.
+ * ath_newstate as the state machine will go from
+ * RUN -> RUN when this happens.
*/
- if (le64toh(ni->ni_tstamp.tsf) >= tsf)
+ if (le64toh(ni->ni_tstamp.tsf) >= tsf) {
+ DPRINTF(sc, ATH_DEBUG_STATE,
+ "ibss merge, rstamp %u tsf %ju "
+ "tstamp %ju\n", rstamp, (uintmax_t)tsf,
+ (uintmax_t)ni->ni_tstamp.tsf);
(void) ieee80211_ibss_merge(ni);
+ }
}
break;
}
@@ -2847,7 +2880,7 @@
struct ath_desc *ds;
struct mbuf *m;
struct ieee80211_node *ni;
- int len;
+ int len, type;
u_int phyerr;
HAL_STATUS status;
@@ -3026,14 +3059,14 @@
goto rx_next;
}
rix = ds->ds_rxstat.rs_rate;
- sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].flags;
+ sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags;
sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix].ieeerate;
sc->sc_rx_th.wr_antsignal = ds->ds_rxstat.rs_rssi;
sc->sc_rx_th.wr_antenna = ds->ds_rxstat.rs_antenna;
/* XXX TSF */
bpf_mtap2(sc->sc_drvbpf,
- &sc->sc_rx, sc->sc_rx_rt_len, m);
+ &sc->sc_rx_th, sc->sc_rx_th_len, m);
}
/*
@@ -3075,11 +3108,11 @@
struct ath_node *an = ATH_NODE(ni);
ATH_RSSI_LPF(an->an_avgrssi, ds->ds_rxstat.rs_rssi);
- ieee80211_input(ni, m,
+ type = ieee80211_input(ni, m,
ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp);
ieee80211_free_node(ni);
} else
- ieee80211_input_all(ic, m,
+ type = ieee80211_input_all(ic, m,
ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp);
if (sc->sc_diversity) {
@@ -3102,8 +3135,7 @@
* is mainly for station mode where we depend on
* periodic beacon frames to trigger the poll event.
*/
- if (sc->sc_ipackets != ifp->if_ipackets) {
- sc->sc_ipackets = ifp->if_ipackets;
+ if (type == IEEE80211_FC0_TYPE_DATA) {
sc->sc_rxrate = ds->ds_rxstat.rs_rate;
ath_led_event(sc, ATH_LED_RX);
} else if (ticks - sc->sc_ledevent >= sc->sc_ledidle)
@@ -3283,14 +3315,106 @@
ath_tx_cleanupq(sc, &sc->sc_txq[i]);
}
+/*
+ * Defragment an mbuf chain, returning at most maxfrags separate
+ * mbufs+clusters. If this is not possible NULL is returned and
+ * the original mbuf chain is left in it's present (potentially
+ * modified) state. We use two techniques: collapsing consecutive
+ * mbufs and replacing consecutive mbufs by a cluster.
+ */
+static struct mbuf *
+ath_defrag(struct mbuf *m0, int how, int maxfrags)
+{
+ struct mbuf *m, *n, *n2, **prev;
+ u_int curfrags;
+
+ /*
+ * Calculate the current number of frags.
+ */
+ curfrags = 0;
+ for (m = m0; m != NULL; m = m->m_next)
+ curfrags++;
+ /*
+ * First, try to collapse mbufs. Note that we always collapse
+ * towards the front so we don't need to deal with moving the
+ * pkthdr. This may be suboptimal if the first mbuf has much
+ * less data than the following.
+ */
+ m = m0;
+again:
+ for (;;) {
+ n = m->m_next;
+ if (n == NULL)
+ break;
+ if ((m->m_flags & M_RDONLY) == 0 &&
+ n->m_len < M_TRAILINGSPACE(m)) {
+ bcopy(mtod(n, void *), mtod(m, char *) + m->m_len,
+ n->m_len);
+ m->m_len += n->m_len;
+ m->m_next = n->m_next;
+ m_free(n);
+ if (--curfrags <= maxfrags)
+ return m0;
+ } else
+ m = n;
+ }
+ KASSERT(maxfrags > 1,
+ ("maxfrags %u, but normal collapse failed", maxfrags));
+ /*
+ * Collapse consecutive mbufs to a cluster.
+ */
+ prev = &m0->m_next; /* NB: not the first mbuf */
+ while ((n = *prev) != NULL) {
+ if ((n2 = n->m_next) != NULL &&
+ n->m_len + n2->m_len < MCLBYTES) {
+ m = m_getcl(how, MT_DATA, 0);
+ if (m == NULL)
+ goto bad;
+ bcopy(mtod(n, void *), mtod(m, void *), n->m_len);
+ bcopy(mtod(n2, void *), mtod(m, char *) + n->m_len,
+ n2->m_len);
+ m->m_len = n->m_len + n2->m_len;
+ m->m_next = n2->m_next;
+ *prev = m;
+ m_free(n);
+ m_free(n2);
+ if (--curfrags <= maxfrags) /* +1 cl -2 mbufs */
+ return m0;
+ /*
+ * Still not there, try the normal collapse
+ * again before we allocate another cluster.
+ */
+ goto again;
+ }
+ prev = &n->m_next;
+ }
+ /*
+ * No place where we can collapse to a cluster; punt.
+ * This can occur if, for example, you request 2 frags
+ * but the packet requires that both be clusters (we
+ * never reallocate the first mbuf to avoid moving the
+ * packet header).
+ */
+bad:
+ return NULL;
+}
+
static int
ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
struct mbuf *m0)
{
+#define CTS_DURATION \
+ ath_hal_computetxtime(ah, rt, IEEE80211_ACK_LEN, cix, AH_TRUE)
+#define updateCTSForBursting(_ah, _ds, _txq) \
+ ath_hal_updateCTSForBursting(_ah, _ds, \
+ _txq->axq_linkbuf != NULL ? _txq->axq_linkbuf->bf_desc : NULL, \
+ _txq->axq_lastdsWithCTS, _txq->axq_gatingds, \
+ txopLimit, CTS_DURATION)
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ath_hal *ah = sc->sc_ah;
struct ifnet *ifp = &sc->sc_if;
+ const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams;
int i, error, iswep, ismcast, keyix, hdrlen, pktlen, try0;
u_int8_t rix, txrate, ctsrate;
u_int8_t cix = 0xff; /* NB: silence compiler */
@@ -3302,6 +3426,8 @@
const HAL_RATE_TABLE *rt;
HAL_BOOL shortPreamble;
struct ath_node *an;
+ struct mbuf *m;
+ u_int pri;
wh = mtod(m0, struct ieee80211_frame *);
iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
@@ -3330,6 +3456,7 @@
* 802.11 layer counts failures and provides
* debugging/diagnostics.
*/
+ m_freem(m0);
return EIO;
}
/*
@@ -3358,8 +3485,8 @@
* Load the DMA map so any coalescing is done. This
* also calculates the number of descriptors we need.
*/
- error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m0,
- ath_mbuf_load_cb, bf,
+ error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
+ bf->bf_segs, &bf->bf_nseg,
BUS_DMA_NOWAIT);
if (error == EFBIG) {
/* XXX packet requires too many descriptors */
@@ -3376,14 +3503,15 @@
*/
if (bf->bf_nseg > ATH_TXDESC) { /* too many desc's, linearize */
sc->sc_stats.ast_tx_linear++;
- m0 = m_defrag(m0, M_DONTWAIT);
- if (m0 == NULL) {
+ m = ath_defrag(m0, M_DONTWAIT, ATH_TXDESC);
+ if (m == NULL) {
+ m_freem(m0);
sc->sc_stats.ast_tx_nombuf++;
- m_freem(m0);
return ENOMEM;
}
- error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m0,
- ath_mbuf_load_cb, bf,
+ m0 = m;
+ error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
+ bf->bf_segs, &bf->bf_nseg,
BUS_DMA_NOWAIT);
if (error != 0) {
sc->sc_stats.ast_tx_busdma++;
@@ -3446,9 +3574,9 @@
/* NB: force all management frames to highest queue */
if (ni->ni_flags & IEEE80211_NODE_QOS) {
/* NB: force all management frames to highest queue */
- txq = sc->sc_ac2q[WME_AC_VO];
+ pri = WME_AC_VO;
} else
- txq = sc->sc_ac2q[WME_AC_BE];
+ pri = WME_AC_BE;
flags |= HAL_TXDESC_INTREQ; /* force interrupt */
break;
case IEEE80211_FC0_TYPE_CTL:
@@ -3462,9 +3590,9 @@
/* NB: force all ctl frames to highest queue */
if (ni->ni_flags & IEEE80211_NODE_QOS) {
/* NB: force all ctl frames to highest queue */
- txq = sc->sc_ac2q[WME_AC_VO];
+ pri = WME_AC_VO;
} else
- txq = sc->sc_ac2q[WME_AC_BE];
+ pri = WME_AC_BE;
flags |= HAL_TXDESC_INTREQ; /* force interrupt */
break;
case IEEE80211_FC0_TYPE_DATA:
@@ -3480,14 +3608,13 @@
* Default all non-QoS traffic to the best-effort queue.
*/
if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
- u_int pri = M_WME_GETAC(m0);
- txq = sc->sc_ac2q[pri];
- if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[pri].wmep_noackPolicy) {
+ pri = M_WME_GETAC(m0);
+ if (cap->cap_wmeParams[pri].wmep_noackPolicy) {
flags |= HAL_TXDESC_NOACK;
sc->sc_stats.ast_tx_noack++;
}
} else
- txq = sc->sc_ac2q[WME_AC_BE];
+ pri = WME_AC_BE;
break;
default:
if_printf(ifp, "bogus frame type 0x%x (%s)\n",
@@ -3496,6 +3623,7 @@
m_freem(m0);
return EIO;
}
+ txq = sc->sc_ac2q[pri];
/*
* When servicing one or more stations in power-save mode
@@ -3606,7 +3734,7 @@
if (vap->iv_rawbpf)
bpf_mtap(vap->iv_rawbpf, m0);
if (sc->sc_drvbpf) {
- sc->sc_tx_th.wt_flags = sc->sc_hwmap[txrate].flags;
+ sc->sc_tx_th.wt_flags = sc->sc_hwmap[txrate].txflags;
if (iswep)
sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
sc->sc_tx_th.wt_rate = sc->sc_hwmap[txrate].ieeerate;
@@ -3686,27 +3814,44 @@
__func__, i, ds->ds_link, ds->ds_data,
ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]);
}
-#if 0
- if ((flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) &&
- !ath_hal_updateCTSForBursting(ah, ds
- , txq->axq_linkbuf != NULL ?
- txq->axq_linkbuf->bf_desc : NULL
- , txq->axq_lastdsWithCTS
- , txq->axq_gatingds
- , IEEE80211_TXOP_TO_US(ic->ic_chanParams.cap_wmeParams[skb->priority].wmep_txopLimit)
- , ath_hal_computetxtime(ah, rt, IEEE80211_ACK_LEN, cix, AH_TRUE))) {
- ATH_TXQ_LOCK(txq);
- txq->axq_lastdsWithCTS = ds;
- /* set gating Desc to final desc */
- txq->axq_gatingds = (struct ath_desc *)txq->axq_link;
- ATH_TXQ_UNLOCK(txq);
- }
-#endif
/*
* Insert the frame on the outbound list and
* pass it on to the hardware.
*/
ATH_TXQ_LOCK(txq);
+ if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) {
+ u_int32_t txopLimit = IEEE80211_TXOP_TO_US(
+ cap->cap_wmeParams[pri].wmep_txopLimit);
+ /*
+ * When bursting, potentially extend the CTS duration
+ * of a previously queued frame to cover this frame
+ * and not exceed the txopLimit. If that can be done
+ * then disable RTS/CTS on this frame since it's now
+ * covered (burst extension). Otherwise we must terminate
+ * the burst before this frame goes out so as not to
+ * violate the WME parameters. All this is complicated
+ * as we need to update the state of packets on the
+ * (live) hardware queue. The logic is buried in the hal
+ * because it's highly chip-specific.
+ */
+ if (txopLimit != 0) {
+ sc->sc_stats.ast_tx_ctsburst++;
+ if (updateCTSForBursting(ah, ds0, txq) == 0) {
+ /*
+ * This frame was not covered by RTS/CTS from
+ * the previous frame in the burst; update the
+ * descriptor pointers so this frame is now
+ * treated as the last frame for extending a
+ * burst.
+ */
+ txq->axq_lastdsWithCTS = ds0;
+ /* set gating Desc to final desc */
+ txq->axq_gatingds =
+ (struct ath_desc *)txq->axq_link;
+ } else
+ sc->sc_stats.ast_tx_ctsext++;
+ }
+ }
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
if (txq->axq_link == NULL) {
ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
@@ -3722,15 +3867,17 @@
(caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth);
}
txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
- ATH_TXQ_UNLOCK(txq);
-
/*
* The CAB queue is started from the SWBA handler since
* frames only go out on DTIM and to avoid possible races.
*/
if (txq != sc->sc_cabq)
ath_hal_txstart(ah, txq->axq_qnum);
+ ATH_TXQ_UNLOCK(txq);
+
return 0;
+#undef updateCTSForBursting
+#undef CTS_DURATION
}
/*
@@ -3741,7 +3888,7 @@
{
struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf;
- struct ath_desc *ds;
+ struct ath_desc *ds, *ds0;
struct ieee80211_node *ni;
struct ath_node *an;
int sr, lr, pri;
@@ -3760,7 +3907,7 @@
ATH_TXQ_UNLOCK(txq);
break;
}
- /* only the last descriptor is needed */
+ ds0 = &bf->bf_desc[0];
ds = &bf->bf_desc[bf->bf_nseg - 1];
status = ath_hal_txprocdesc(ah, ds);
#ifdef AR_DEBUG
@@ -3771,12 +3918,10 @@
ATH_TXQ_UNLOCK(txq);
break;
}
-#if 0
- if (bf->bf_desc == txq->axq_lastdsWithCTS)
+ if (ds0 == txq->axq_lastdsWithCTS)
txq->axq_lastdsWithCTS = NULL;
if (ds == txq->axq_gatingds)
txq->axq_gatingds = NULL;
-#endif
ATH_TXQ_REMOVE_HEAD(txq, bf_list);
ATH_TXQ_UNLOCK(txq);
@@ -3814,7 +3959,7 @@
/*
* Hand the descriptor to the rate control algorithm.
*/
- ath_rate_tx_complete(sc, an, ds);
+ ath_rate_tx_complete(sc, an, ds, ds0);
/*
* Reclaim reference to node.
*
@@ -4617,9 +4762,13 @@
}
sc->sc_hwmap[i].ieeerate =
rt->info[ix].dot11Rate & IEEE80211_RATE_VAL;
+ sc->sc_hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
if (rt->info[ix].shortPreamble ||
rt->info[ix].phy == IEEE80211_T_OFDM)
- sc->sc_hwmap[i].flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+ sc->sc_hwmap[i].txflags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+ /* NB: receive frames include FCS */
+ sc->sc_hwmap[i].rxflags = sc->sc_hwmap[i].txflags |
+ IEEE80211_RADIOTAP_F_FCS;
/* setup blink rate table to avoid per-packet lookup */
for (j = 0; j < N(blinkrates)-1; j++)
if (blinkrates[j].rate == sc->sc_hwmap[i].ieeerate)
@@ -5056,8 +5205,8 @@
sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len);
sc->sc_tx_th.wt_ihdr.it_present = htole32(ATH_TX_RADIOTAP_PRESENT);
- sc->sc_rx_rt_len = roundup(sizeof(sc->sc_rx_th), sizeof(u_int32_t));
- sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_rt_len);
+ sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(u_int32_t));
+ sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len);
sc->sc_rx_th.wr_ihdr.it_present = htole32(ATH_RX_RADIOTAP_PRESENT);
}
==== //depot/projects/vap/sys/dev/ath/if_ath_pci.c#2 (text+ko) ====
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath_pci.c,v 1.11 2005/01/18 18:08:16 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath_pci.c,v 1.12 2005/03/05 19:06:12 imp Exp $");
/*
* PCI/Cardbus front-end for the Atheros Wireless LAN controller driver.
@@ -90,7 +90,7 @@
devname = ath_hal_probe(pci_get_vendor(dev), pci_get_device(dev));
if (devname != NULL) {
device_set_desc(dev, devname);
- return 0;
+ return BUS_PROBE_DEFAULT;
}
return ENXIO;
}
==== //depot/projects/vap/sys/dev/ath/if_athioctl.h#2 (text+ko) ====
@@ -33,7 +33,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD: src/sys/dev/ath/if_athioctl.h,v 1.9 2004/12/31 22:41:45 sam Exp $
+ * $FreeBSD: src/sys/dev/ath/if_athioctl.h,v 1.10 2005/03/30 20:13:08 sam Exp $
*/
/*
@@ -75,6 +75,8 @@
u_int32_t ast_tx_shortpre;/* tx frames with short preamble */
u_int32_t ast_tx_altrate; /* tx frames with alternate rate */
u_int32_t ast_tx_protect; /* tx frames with protection */
+ u_int32_t ast_tx_ctsburst;/* tx frames with cts and bursting */
+ u_int32_t ast_tx_ctsext; /* tx frames with cts extension */
u_int32_t ast_rx_nombuf; /* rx setup failed 'cuz no mbuf */
u_int32_t ast_rx_busdma; /* rx setup failed for dma resrcs */
u_int32_t ast_rx_orn; /* rx failed 'cuz of desc overrun */
==== //depot/projects/vap/sys/dev/ath/if_athrate.h#3 (text+ko) ====
@@ -34,7 +34,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD: src/sys/dev/ath/if_athrate.h,v 1.2 2004/12/31 22:41:45 sam Exp $
+ * $FreeBSD: src/sys/dev/ath/if_athrate.h,v 1.4 2005/04/02 18:54:30 sam Exp $
*/
#ifndef _ATH_RATECTRL_H_
#define _ATH_RATECTRL_H_
@@ -121,14 +121,14 @@
* can be transmitted with multi-rate retry.
*/
void ath_rate_findrate(struct ath_softc *, struct ath_node *,
- HAL_BOOL shortPreamble, size_t frameLen,
+ int shortPreamble, size_t frameLen,
u_int8_t *rix, int *try0, u_int8_t *txrate);
/*
* Setup any extended (multi-rate) descriptor state for a data packet.
* The rate index returned by ath_rate_findrate is passed back in.
*/
void ath_rate_setupxtxdesc(struct ath_softc *, struct ath_node *,
- struct ath_desc *, HAL_BOOL shortPreamble, u_int8_t rix);
+ struct ath_desc *, int shortPreamble, u_int8_t rix);
/*
* Update rate control state for a packet associated with the
* supplied transmit descriptor. The routine is invoked both
@@ -136,5 +136,5 @@
* failed (consult the descriptor for details).
*/
void ath_rate_tx_complete(struct ath_softc *, struct ath_node *,
- const struct ath_desc *);
+ const struct ath_desc *last, const struct ath_desc *first);
#endif /* _ATH_RATECTRL_H_ */
==== //depot/projects/vap/sys/dev/ath/if_athvar.h#4 (text+ko) ====
@@ -33,7 +33,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD: src/sys/dev/ath/if_athvar.h,v 1.19 2005/01/18 19:42:17 sam Exp $
+ * $FreeBSD: src/sys/dev/ath/if_athvar.h,v 1.23 2005/04/12 17:56:43 sam Exp $
*/
/*
@@ -205,6 +205,7 @@
sc_hastpc : 1, /* per-packet TPC support */
sc_ledstate: 1, /* LED on/off state */
sc_blinking: 1, /* LED blink operation active */
+ sc_mcastkey: 1, /* mcast key cache search */
sc_beacons : 1; /* beacons running */
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list