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