From owner-p4-projects@FreeBSD.ORG Tue May 3 16:28:19 2005 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7B1A116A4D0; Tue, 3 May 2005 16:28:19 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 548B416A4CE for ; Tue, 3 May 2005 16:28:19 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9F27643D39 for ; Tue, 3 May 2005 16:28:18 +0000 (GMT) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j43GSDZn052985 for ; Tue, 3 May 2005 16:28:13 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j43GSDp2052979 for perforce@freebsd.org; Tue, 3 May 2005 16:28:13 GMT (envelope-from sam@freebsd.org) Date: Tue, 3 May 2005 16:28:13 GMT Message-Id: <200505031628.j43GSDp2052979@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 Subject: PERFORCE change 76439 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 03 May 2005 16:28:20 -0000 http://perforce.freebsd.org/chv.cgi?CH=76439 Change 76439 by sam@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 -__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 -__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 -__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 -__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 -__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 -__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) <<<