Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 18 Jul 2005 16:59:41 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 80454 for review
Message-ID:  <200507181659.j6IGxfmu064367@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=80454

Change 80454 by sam@sam_ebb on 2005/07/18 16:58:57

	o update for new scan api
	o more of the 11j support
	o track revised api's from vap work
	o separate min rate index for mgt/ctl frames
	o purge defrag test glop

Affected files ...

.. //depot/projects/wifi/sys/dev/ath/if_ath.c#87 edit
.. //depot/projects/wifi/sys/dev/ath/if_athvar.h#37 edit

Differences ...

==== //depot/projects/wifi/sys/dev/ath/if_ath.c#87 (text+ko) ====

@@ -159,18 +159,20 @@
 static void	ath_stoprecv(struct ath_softc *);
 static int	ath_startrecv(struct ath_softc *);
 static void	ath_chan_change(struct ath_softc *, struct ieee80211_channel *);
-static void	ath_next_scan(void *);
+static void	ath_scan_start(struct ieee80211com *);
+static void	ath_scan_end(struct ieee80211com *);
+static void	ath_set_channel(struct ieee80211com *);
 static void	ath_calibrate(void *);
 static int	ath_newstate(struct ieee80211com *, enum ieee80211_state, int);
 static void	ath_setup_stationkey(struct ieee80211_node *);
-static void	ath_newassoc(struct ieee80211com *,
-			struct ieee80211_node *, int);
+static void	ath_newassoc(struct ieee80211_node *, int);
 static int	ath_getchannels(struct ath_softc *, u_int cc,
 			HAL_BOOL outdoor, HAL_BOOL xchanmode);
 static void	ath_led_event(struct ath_softc *, int);
 static void	ath_update_txpow(struct ath_softc *);
 
 static int	ath_rate_setup(struct ath_softc *, u_int mode);
+static void	ath_setup_subrates(struct ath_softc *);
 static void	ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
 
 static void	ath_sysctlattach(struct ath_softc *);
@@ -180,9 +182,6 @@
 SYSCTL_DECL(_hw_ath);
 
 /* XXX validate sysctl values */
-static	int ath_dwelltime = 200;		/* 5 channels/second */
-SYSCTL_INT(_hw_ath, OID_AUTO, dwell, CTLFLAG_RW, &ath_dwelltime,
-	    0, "channel dwell time (ms) for AP/station scanning");
 static	int ath_calinterval = 30;		/* calibrate every 30 secs */
 SYSCTL_INT(_hw_ath, OID_AUTO, calibrate, CTLFLAG_RW, &ath_calinterval,
 	    0, "chip calibration interval (secs)");
@@ -360,6 +359,7 @@
 	ath_rate_setup(sc, IEEE80211_MODE_11G);
 	ath_rate_setup(sc, IEEE80211_MODE_TURBO_A);
 	ath_rate_setup(sc, IEEE80211_MODE_TURBO_G);
+	ath_setup_subrates(sc);		/* half/quarter rates */
 	/* NB: setup here so ath_rate_update is happy */
 	ath_setcurmode(sc, IEEE80211_MODE_11A);
 
@@ -371,7 +371,6 @@
 		if_printf(ifp, "failed to allocate descriptors: %d\n", error);
 		goto bad;
 	}
-	callout_init(&sc->sc_scan_ch, debug_mpsafenet ? CALLOUT_MPSAFE : 0);
 	callout_init(&sc->sc_cal_ch, CALLOUT_MPSAFE);
 
 	ATH_TXBUF_LOCK_INIT(sc);
@@ -503,6 +502,7 @@
 		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
 		| IEEE80211_C_SHSLOT		/* short slot time supported */
 		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
+		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
 		;
 	/*
 	 * Query the hal to figure out h/w crypto support.
@@ -592,6 +592,9 @@
 	ic->ic_recv_mgmt = ath_recv_mgmt;
 	sc->sc_newstate = ic->ic_newstate;
 	ic->ic_newstate = ath_newstate;
+	ic->ic_scan_start = ath_scan_start;
+	ic->ic_scan_end = ath_scan_end;
+	ic->ic_set_channel = ath_set_channel;
 	ic->ic_crypto.cs_key_alloc = ath_key_alloc;
 	ic->ic_crypto.cs_key_delete = ath_key_delete;
 	ic->ic_crypto.cs_key_set = ath_key_set;
@@ -843,14 +846,20 @@
 		CHANNEL_B,		/* IEEE80211_MODE_11B */
 		CHANNEL_PUREG,		/* IEEE80211_MODE_11G */
 		0,			/* IEEE80211_MODE_FH */
-		CHANNEL_T,		/* IEEE80211_MODE_TURBO_A */
+		CHANNEL_108A,		/* IEEE80211_MODE_TURBO_A */
 		CHANNEL_108G		/* IEEE80211_MODE_TURBO_G */
 	};
 	enum ieee80211_phymode mode = ieee80211_chan2mode(chan);
+	int flags;
 
 	KASSERT(mode < N(modeflags), ("unexpected phy mode %u", mode));
 	KASSERT(modeflags[mode] != 0, ("mode %u undefined", mode));
-	return modeflags[mode];
+	flags = modeflags[mode];
+	if (IEEE80211_IS_CHAN_HALF(chan))
+		flags |= CHANNEL_HALF;
+	else if (IEEE80211_IS_CHAN_QUARTER(chan))
+		flags |= CHANNEL_QUARTER;
+	return flags;
 #undef N
 }
 
@@ -1449,7 +1458,7 @@
 				 * to the 802.11 layer and continue.  We'll get
 				 * the frame back when the time is right.
 				 */
-				ieee80211_pwrsave(ic, ni, m);
+				ieee80211_pwrsave(ni, m);
 				goto reclaim;
 			}
 			/* calculate priority so we can find the tx queue */
@@ -1960,14 +1969,15 @@
  *   - when scanning
  */
 static u_int32_t
-ath_calcrxfilter(struct ath_softc *sc, enum ieee80211_state state)
+ath_calcrxfilter(struct ath_softc *sc)
 {
+#define	RX_FILTER_PRESERVE	(HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR)
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ath_hal *ah = sc->sc_ah;
 	struct ifnet *ifp = sc->sc_ifp;
 	u_int32_t rfilt;
 
-	rfilt = (ath_hal_getrxfilter(ah) & HAL_RX_FILTER_PHYERR)
+	rfilt = (ath_hal_getrxfilter(ah) & RX_FILTER_PRESERVE)
 	      | HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST;
 	if (ic->ic_opmode != IEEE80211_M_STA)
 		rfilt |= HAL_RX_FILTER_PROBEREQ;
@@ -1976,9 +1986,10 @@
 		rfilt |= HAL_RX_FILTER_PROM;
 	if (ic->ic_opmode == IEEE80211_M_STA ||
 	    ic->ic_opmode == IEEE80211_M_IBSS ||
-	    state == IEEE80211_S_SCAN)
+	    sc->sc_scanning)
 		rfilt |= HAL_RX_FILTER_BEACON;
 	return rfilt;
+#undef RX_FILTER_PRESERVE
 }
 
 static void
@@ -1992,7 +2003,7 @@
 	struct ifmultiaddr *ifma;
 
 	/* configure rx filter */
-	rfilt = ath_calcrxfilter(sc, ic->ic_state);
+	rfilt = ath_calcrxfilter(sc);
 	ath_hal_setrxfilter(ah, rfilt);
 
 	/* configure operational mode */
@@ -2181,10 +2192,10 @@
 	struct ieee80211com *ic = ni->ni_ic;
 	struct mbuf *m = bf->bf_m;
 	struct ath_hal *ah = sc->sc_ah;
-	struct ath_node *an = ATH_NODE(ni);
 	struct ath_desc *ds;
 	int flags, antenna;
-	u_int8_t rate;
+	const HAL_RATE_TABLE *rt;
+	u_int8_t rix, rate;
 
 	DPRINTF(sc, ATH_DEBUG_BEACON, "%s: m %p len %u\n",
 		__func__, m, m->m_len);
@@ -2216,10 +2227,11 @@
 	 * Calculate rate code.
 	 * XXX everything at min xmit rate
 	 */
+	rix = sc->sc_minrateix;
+	rt = sc->sc_currates;
+	rate = rt->info[rix].rateCode;
 	if (USE_SHPREAMBLE(ic))
-		rate = an->an_tx_mgtratesp;
-	else
-		rate = an->an_tx_mgtrate;
+		rate |= rt->info[rix].shortPreamble;
 	ath_hal_setuptxdesc(ah, ds
 		, m->m_len + IEEE80211_CRC_LEN	/* frame length */
 		, sizeof(struct ieee80211_frame)/* header length */
@@ -2575,6 +2587,7 @@
 		if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol)
 			ath_beacon_proc(sc, 0);
 	}
+	sc->sc_syncbeacon = 0;
 #undef TSF_TO_TU
 }
 
@@ -2931,6 +2944,14 @@
 	case IEEE80211_FC0_SUBTYPE_BEACON:
 		/* update rssi statistics for use by the hal */
 		ATH_RSSI_LPF(ATH_NODE(ni)->an_halstats.ns_avgbrssi, rssi);
+		if (sc->sc_syncbeacon &&
+		    ni == ic->ic_bss && ic->ic_state == IEEE80211_S_RUN) {
+			/*
+			 * Resync beacon timers using the tsf of the beacon
+			 * frame we just received.
+			 */
+			ath_beacon_config(sc);
+		}
 		/* fall thru... */
 	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 		if (ic->ic_opmode == IEEE80211_M_IBSS &&
@@ -2951,7 +2972,7 @@
 				    "ibss merge, rstamp %u tsf %ju "
 				    "tstamp %ju\n", rstamp, (uintmax_t)tsf,
 				    (uintmax_t)ni->ni_tstamp.tsf);
-				(void) ieee80211_ibss_merge(ic, ni);
+				(void) ieee80211_ibss_merge(ni);
 			}
 		}
 		break;
@@ -3202,7 +3223,8 @@
 		 * frame; it'll be dropped where it's not wanted.
 		 */
 		if (ds->ds_rxstat.rs_keyix != HAL_RXKEYIX_INVALID &&
-		    (ni = sc->sc_keyixmap[ds->ds_rxstat.rs_keyix]) != NULL) {
+		    (ni = sc->sc_keyixmap[ds->ds_rxstat.rs_keyix]) != NULL &&
+		    ieee80211_node_refcnt(ni) > 1) {
 			/*
 			 * Fast path: node is present in the key map;
 			 * grab a reference for processing the frame.
@@ -3443,18 +3465,6 @@
 			ath_tx_cleanupq(sc, &sc->sc_txq[i]);
 }
 
-SYSCTL_NODE(_hw_ath, OID_AUTO, defrag, CTLFLAG_RD, 0, "defrag testing");
-static int ath_maxfrags = 4;
-SYSCTL_INT(_hw_ath_defrag, OID_AUTO, max, CTLFLAG_RW, &ath_maxfrags, 0, "");
-static int ath_defrags;
-SYSCTL_INT(_hw_ath_defrag, OID_AUTO, calls, CTLFLAG_RW, &ath_defrags, 0, "");
-static int ath_collectedfrags;
-SYSCTL_INT(_hw_ath_defrag, OID_AUTO, combined, CTLFLAG_RW, &ath_collectedfrags, 0, "");
-static int ath_replacedfrags;
-SYSCTL_INT(_hw_ath_defrag, OID_AUTO, replaced, CTLFLAG_RW, &ath_replacedfrags, 0, "");
-static int ath_defragsfail;
-SYSCTL_INT(_hw_ath_defrag, OID_AUTO, fail, CTLFLAG_RW, &ath_defragsfail, 0, "");
-
 /*
  * Defragment an mbuf chain, returning at most maxfrags separate
  * mbufs+clusters.  If this is not possible NULL is returned and
@@ -3468,14 +3478,12 @@
 	struct mbuf *m, *n, *n2, **prev;
 	u_int curfrags;
 
-ath_defrags++;/*XXX*/
 	/*
 	 * Calculate the current number of frags.
 	 */
 	curfrags = 0;
 	for (m = m0; m != NULL; m = m->m_next)
 		curfrags++;
-if (curfrags <= maxfrags) return m0; /* XXX for testing */
 	/*
 	 * First, try to collapse mbufs.  Note that we always collapse
 	 * towards the front so we don't need to deal with moving the
@@ -3495,7 +3503,6 @@
 			m->m_len += n->m_len;
 			m->m_next = n->m_next;
 			m_free(n);
-ath_collectedfrags++;/*XXX*/
 			if (--curfrags <= maxfrags)
 				return m0;
 		} else
@@ -3521,7 +3528,6 @@
 			*prev = m;
 			m_free(n);
 			m_free(n2);
-ath_replacedfrags++;/*XXX*/
 			if (--curfrags <= maxfrags)	/* +1 cl -2 mbufs */
 				return m0;
 			/*
@@ -3540,7 +3546,6 @@
 	 * packet header).
 	 */
 bad:
-ath_defragsfail++;/*XXX*/
 	return NULL;
 }
 
@@ -3632,8 +3637,6 @@
 
 	pktlen += IEEE80211_CRC_LEN;
 
-m = ath_defrag(m0, M_DONTWAIT, ath_maxfrags); if (m != NULL) m0 = m;	/*XXX*/
-
 	/*
 	 * Load the DMA map so any coalescing is done.  This
 	 * also calculates the number of descriptors we need.
@@ -3718,12 +3721,11 @@
 			atype = HAL_PKT_TYPE_ATIM;
 		else
 			atype = HAL_PKT_TYPE_NORMAL;	/* XXX */
-		rix = 0;			/* XXX lowest rate */
+		rix = sc->sc_minrateix;
+		txrate = rt->info[rix].rateCode;
+		if (shortPreamble)
+			txrate |= rt->info[rix].shortPreamble;
 		try0 = ATH_TXMAXTRY;
-		if (shortPreamble)
-			txrate = an->an_tx_mgtratesp;
-		else
-			txrate = an->an_tx_mgtrate;
 		/* NB: force all management frames to highest queue */
 		if (ni->ni_flags & IEEE80211_NODE_QOS) {
 			/* NB: force all management frames to highest queue */
@@ -3734,12 +3736,11 @@
 		break;
 	case IEEE80211_FC0_TYPE_CTL:
 		atype = HAL_PKT_TYPE_PSPOLL;	/* stop setting of duration */
-		rix = 0;			/* XXX lowest rate */
+		rix = sc->sc_minrateix;
+		txrate = rt->info[rix].rateCode;
+		if (shortPreamble)
+			txrate |= rt->info[rix].shortPreamble;
 		try0 = ATH_TXMAXTRY;
-		if (shortPreamble)
-			txrate = an->an_tx_mgtratesp;
-		else
-			txrate = an->an_tx_mgtrate;
 		/* NB: force all ctl frames to highest queue */
 		if (ni->ni_flags & IEEE80211_NODE_QOS) {
 			/* NB: force all ctl frames to highest queue */
@@ -4491,16 +4492,6 @@
 	return 0;
 }
 
-static void
-ath_next_scan(void *arg)
-{
-	struct ath_softc *sc = arg;
-	struct ieee80211com *ic = &sc->sc_ic;
-
-	if (ic->ic_state == IEEE80211_S_SCAN)
-		ieee80211_next_scan(ic);
-}
-
 /*
  * Periodically recalibrate the PHY to account
  * for temperature/environment changes.
@@ -4533,6 +4524,61 @@
 	callout_reset(&sc->sc_cal_ch, ath_calinterval * hz, ath_calibrate, sc);
 }
 
+static void
+ath_scan_start(struct ieee80211com *ic)
+{
+	struct ifnet *ifp = ic->ic_ifp;
+	struct ath_softc *sc = ifp->if_softc;
+	struct ath_hal *ah = sc->sc_ah;
+	u_int32_t rfilt;
+
+	/* XXX calibration timer? */
+
+	sc->sc_scanning = 1;
+	sc->sc_syncbeacon = 0;
+	rfilt = ath_calcrxfilter(sc);
+	ath_hal_setrxfilter(ah, rfilt);
+	ath_hal_setassocid(ah, ifp->if_broadcastaddr, 0);
+
+	DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0\n",
+		 __func__, rfilt, ether_sprintf(ifp->if_broadcastaddr));
+}
+
+static void
+ath_scan_end(struct ieee80211com *ic)
+{
+	struct ifnet *ifp = ic->ic_ifp;
+	struct ath_softc *sc = ifp->if_softc;
+	struct ath_hal *ah = sc->sc_ah;
+	u_int32_t rfilt;
+
+	sc->sc_scanning = 0;
+	rfilt = ath_calcrxfilter(sc);
+	ath_hal_setrxfilter(ah, rfilt);
+	ath_hal_setassocid(ah, sc->sc_curbssid, sc->sc_curaid);
+
+	DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0x%x\n",
+		 __func__, rfilt, ether_sprintf(sc->sc_curbssid),
+		 sc->sc_curaid);
+}
+
+static void
+ath_set_channel(struct ieee80211com *ic)
+{
+	struct ifnet *ifp = ic->ic_ifp;
+	struct ath_softc *sc = ifp->if_softc;
+
+	(void) ath_chan_set(sc, ic->ic_curchan);
+	/*
+	 * If we are returning to our bss channel then mark state
+	 * so the next recv'd beacon's tsf will be used to sync the
+	 * beacon timers.  Note that since we only hear beacons in
+	 * sta/ibss mode this has no effect in other operating modes.
+	 */
+	if (!sc->sc_scanning && ic->ic_curchan == ic->ic_bsschan)
+		sc->sc_syncbeacon = 1;
+}
+
 static int
 ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 {
@@ -4540,8 +4586,7 @@
 	struct ath_softc *sc = ifp->if_softc;
 	struct ath_hal *ah = sc->sc_ah;
 	struct ieee80211_node *ni;
-	int i, error;
-	const u_int8_t *bssid;
+	int i, error, stamode;
 	u_int32_t rfilt;
 	static const HAL_LED_STATE leds[] = {
 	    HAL_LED_INIT,	/* IEEE80211_S_INIT */
@@ -4555,7 +4600,6 @@
 		ieee80211_state_name[ic->ic_state],
 		ieee80211_state_name[nstate]);
 
-	callout_stop(&sc->sc_scan_ch);
 	callout_stop(&sc->sc_cal_ch);
 	ath_hal_setledstate(ah, leds[nstate]);	/* set LED */
 
@@ -4572,26 +4616,30 @@
 		goto done;
 	}
 	ni = ic->ic_bss;
-	error = ath_chan_set(sc, ic->ic_curchan);
-	if (error != 0)
-		goto bad;
-	rfilt = ath_calcrxfilter(sc, nstate);
-	if (nstate == IEEE80211_S_SCAN)
-		bssid = ifp->if_broadcastaddr;
-	else
-		bssid = ni->ni_bssid;
+
+	rfilt = ath_calcrxfilter(sc);
+	stamode = (ic->ic_opmode == IEEE80211_M_STA ||
+		   ic->ic_opmode == IEEE80211_M_IBSS ||
+		   ic->ic_opmode == IEEE80211_M_AHDEMO);
+	if (stamode && nstate == IEEE80211_S_RUN) {
+		sc->sc_curaid = ni->ni_associd;
+		IEEE80211_ADDR_COPY(sc->sc_curbssid, ni->ni_bssid);
+	} else
+		sc->sc_curaid = 0;
+
+	DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0x%x\n",
+		 __func__, rfilt, ether_sprintf(sc->sc_curbssid),
+		 sc->sc_curaid);
+
 	ath_hal_setrxfilter(ah, rfilt);
-	DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s\n",
-		 __func__, rfilt, ether_sprintf(bssid));
+	if (stamode)
+		ath_hal_setassocid(ah, sc->sc_curbssid, ni->ni_associd);
 
-	if (nstate == IEEE80211_S_RUN && ic->ic_opmode == IEEE80211_M_STA)
-		ath_hal_setassocid(ah, bssid, ni->ni_associd);
-	else
-		ath_hal_setassocid(ah, bssid, 0);
-	if (ic->ic_flags & IEEE80211_F_PRIVACY) {
+	if (ic->ic_opmode != IEEE80211_M_STA &&
+	    (ic->ic_flags & IEEE80211_F_PRIVACY)) {
 		for (i = 0; i < IEEE80211_WEP_NKID; i++)
 			if (ath_hal_keyisvalid(ah, i))
-				ath_hal_keysetmac(ah, i, bssid);
+				ath_hal_keysetmac(ah, i, ni->ni_bssid);
 	}
 
 	/*
@@ -4672,10 +4720,6 @@
 		/* start periodic recalibration timer */
 		callout_reset(&sc->sc_cal_ch, ath_calinterval * hz,
 			ath_calibrate, sc);
-	} else if (nstate == IEEE80211_S_SCAN) {
-		/* start ap/neighbor scan timer */
-		callout_reset(&sc->sc_scan_ch, (ath_dwelltime * hz) / 1000,
-			ath_next_scan, sc);
 	}
 bad:
 	return error;
@@ -4717,8 +4761,9 @@
  * param tells us if this is the first time or not.
  */
 static void
-ath_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
+ath_newassoc(struct ieee80211_node *ni, int isnew)
 {
+	struct ieee80211com *ic = ni->ni_ic;
 	struct ath_softc *sc = ic->ic_ifp->if_softc;
 
 	ath_rate_newassoc(sc, ATH_NODE(ni), isnew);
@@ -4855,51 +4900,74 @@
 	ic->ic_bss->ni_txpower = txpow;
 }
 
+static void
+rate_setup(struct ath_softc *sc,
+	const HAL_RATE_TABLE *rt, struct ieee80211_rateset *rs)
+{
+	int i, maxrates;
+
+	if (rt->rateCount > IEEE80211_RATE_MAXSIZE) {
+		DPRINTF(sc, ATH_DEBUG_ANY,
+			"%s: rate table too small (%u > %u)\n",
+		       __func__, rt->rateCount, IEEE80211_RATE_MAXSIZE);
+		maxrates = IEEE80211_RATE_MAXSIZE;
+	} else
+		maxrates = rt->rateCount;
+	for (i = 0; i < maxrates; i++)
+		rs->rs_rates[i] = rt->info[i].dot11Rate;
+	rs->rs_nrates = maxrates;
+}
+
 static int
 ath_rate_setup(struct ath_softc *sc, u_int mode)
 {
 	struct ath_hal *ah = sc->sc_ah;
 	struct ieee80211com *ic = &sc->sc_ic;
 	const HAL_RATE_TABLE *rt;
-	struct ieee80211_rateset *rs;
-	int i, maxrates;
 
 	switch (mode) {
 	case IEEE80211_MODE_11A:
-		sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11A);
+		rt = ath_hal_getratetable(ah, HAL_MODE_11A);
 		break;
 	case IEEE80211_MODE_11B:
-		sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11B);
+		rt = ath_hal_getratetable(ah, HAL_MODE_11B);
 		break;
 	case IEEE80211_MODE_11G:
-		sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11G);
+		rt = ath_hal_getratetable(ah, HAL_MODE_11G);
 		break;
 	case IEEE80211_MODE_TURBO_A:
-		sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_TURBO);
+		rt = ath_hal_getratetable(ah, HAL_MODE_TURBO);
 		break;
 	case IEEE80211_MODE_TURBO_G:
-		sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_108G);
+		rt = ath_hal_getratetable(ah, HAL_MODE_108G);
 		break;
 	default:
 		DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid mode %u\n",
 			__func__, mode);
 		return 0;
 	}
-	rt = sc->sc_rates[mode];
-	if (rt == NULL)
+	sc->sc_rates[mode] = rt;
+	if (rt != NULL) {
+		rate_setup(sc, rt, &ic->ic_sup_rates[mode]);
+		return 1;
+	} else
 		return 0;
-	if (rt->rateCount > IEEE80211_RATE_MAXSIZE) {
-		DPRINTF(sc, ATH_DEBUG_ANY,
-			"%s: rate table too small (%u > %u)\n",
-			__func__, rt->rateCount, IEEE80211_RATE_MAXSIZE);
-		maxrates = IEEE80211_RATE_MAXSIZE;
-	} else
-		maxrates = rt->rateCount;
-	rs = &ic->ic_sup_rates[mode];
-	for (i = 0; i < maxrates; i++)
-		rs->rs_rates[i] = rt->info[i].dot11Rate;
-	rs->rs_nrates = maxrates;
-	return 1;
+}
+
+static void
+ath_setup_subrates(struct ath_softc *sc)
+{
+	struct ath_hal *ah = sc->sc_ah;
+	struct ieee80211com *ic = &sc->sc_ic;
+
+	sc->sc_half_rates = ath_hal_getratetable(ah, HAL_MODE_11A_HALF_RATE);
+	if (sc->sc_half_rates != NULL)
+		rate_setup(sc, sc->sc_half_rates, &ic->ic_sup_half_rates);
+
+	sc->sc_quarter_rates =
+		ath_hal_getratetable(ah, HAL_MODE_11A_QUARTER_RATE);
+	if (sc->sc_quarter_rates != NULL)
+		rate_setup(sc, sc->sc_quarter_rates, &ic->ic_sup_quarter_rates);
 }
 
 static void
@@ -4970,6 +5038,8 @@
 	 */
 	sc->sc_protrix = (mode == IEEE80211_MODE_11G ? 1 : 0);
 	/* NB: caller is responsible for reseting rate control state */
+	/* rate index used to send management frames */
+	sc->sc_minrateix = 0;
 #undef N
 }
 

==== //depot/projects/wifi/sys/dev/ath/if_athvar.h#37 (text+ko) ====

@@ -226,13 +226,19 @@
 				sc_ledstate: 1,	/* LED on/off state */
 				sc_blinking: 1,	/* LED blink operation active */
 				sc_mcastkey: 1,	/* mcast key cache search */
+				sc_scanning: 1,	/* scanning active */
+				sc_syncbeacon:1,/* sync/resync beacon timers */
 				sc_hasclrkey:1;	/* CLR key supported */
 						/* rate tables */
 	const HAL_RATE_TABLE	*sc_rates[IEEE80211_MODE_MAX];
+	const HAL_RATE_TABLE	*sc_half_rates;	/* half rate table */
+	const HAL_RATE_TABLE	*sc_quarter_rates;/* quarter rate table */
 	const HAL_RATE_TABLE	*sc_currates;	/* current rate table */
 	enum ieee80211_phymode	sc_curmode;	/* current phy mode */
 	u_int16_t		sc_curtxpow;	/* current tx power limit */
+	u_int16_t		sc_curaid;	/* current association id */
 	HAL_CHANNEL		sc_curchan;	/* current h/w channel */
+	u_int8_t		sc_curbssid[IEEE80211_ADDR_LEN];
 	u_int8_t		sc_rixmap[256];	/* IEEE to h/w rate table ix */
 	struct {
 		u_int8_t	ieeerate;	/* IEEE rate */
@@ -241,6 +247,7 @@
 		u_int16_t	ledon;		/* softled on time */
 		u_int16_t	ledoff;		/* softled off time */
 	} sc_hwmap[32];				/* h/w rate ix mappings */
+	u_int8_t		sc_minrateix;	/* min h/w rate index */
 	u_int8_t		sc_protrix;	/* protection rate index */
 	u_int8_t		sc_lastdatarix;	/* last data frame rate index */
 	u_int			sc_fftxqmin;	/* min frames before staging */
@@ -309,7 +316,6 @@
 	} sc_updateslot;			/* slot time update fsm */
 
 	struct callout		sc_cal_ch;	/* callout handle for cals */
-	struct callout		sc_scan_ch;	/* callout handle for scan */
 	HAL_NODE_STATS		sc_halstats;	/* station-mode rssi stats */
 };
 #define	sc_tx_th		u_tx_rt.th



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200507181659.j6IGxfmu064367>