Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 5 Oct 2007 04:56:12 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 127216 for review
Message-ID:  <200710050456.l954uCTX047861@repoman.freebsd.org>

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

Change 127216 by sam@sam_ebb on 2007/10/05 04:55:38

	Checkpoint work:
	o add amrr rate control; need to check if data_txcnt is
	  the retry count (for now assume it's tries and -1)
	o hold node for tx mgt frames and implement M_TXCB
	o fix 4-byte register read that should be 2 bytes
	  (noticed in obsd commit)

Affected files ...

.. //depot/projects/wifi/sys/dev/bwi/bwimac.c#2 edit
.. //depot/projects/wifi/sys/dev/bwi/bwiphy.c#2 edit
.. //depot/projects/wifi/sys/dev/bwi/bwirf.c#2 edit
.. //depot/projects/wifi/sys/dev/bwi/if_bwi.c#2 edit
.. //depot/projects/wifi/sys/dev/bwi/if_bwi_pci.c#2 edit
.. //depot/projects/wifi/sys/dev/bwi/if_bwivar.h#2 edit

Differences ...

==== //depot/projects/wifi/sys/dev/bwi/bwimac.c#2 (text+ko) ====

@@ -64,6 +64,7 @@
 
 #include <net80211/ieee80211_var.h>
 #include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_amrr.h>
 
 #include <machine/bus.h>
 
@@ -345,7 +346,7 @@
 	/*
 	 * Initialize PHY
 	 */
-	CSR_WRITE_4(sc, BWI_BBP_ATTEN, 0);
+	CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
 	bwi_phy_init(mac);
 
 	/* TODO: interference mitigation */

==== //depot/projects/wifi/sys/dev/bwi/bwiphy.c#2 (text+ko) ====

@@ -61,6 +61,7 @@
 
 #include <net80211/ieee80211_var.h>
 #include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_amrr.h>
 
 #include <machine/bus.h>
 

==== //depot/projects/wifi/sys/dev/bwi/bwirf.c#2 (text+ko) ====

@@ -61,6 +61,7 @@
 
 #include <net80211/ieee80211_var.h>
 #include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_amrr.h>
 
 #include <machine/bus.h>
 

==== //depot/projects/wifi/sys/dev/bwi/if_bwi.c#2 (text+ko) ====

@@ -62,6 +62,7 @@
 #include <net80211/ieee80211_var.h>
 #include <net80211/ieee80211_radiotap.h>
 #include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_amrr.h>
 
 #include <net/bpf.h>
 
@@ -100,6 +101,9 @@
 static void	bwi_scan_end(struct ieee80211com *);
 static int	bwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
 static void	bwi_updateslot(struct ifnet *);
+static struct ieee80211_node *bwi_node_alloc(struct ieee80211_node_table *);
+static void	bwi_newassoc(struct ieee80211_node *, int);
+static void	bwi_amrr_timeout(void *);
 static int	bwi_media_change(struct ifnet *);
 
 static void	bwi_calibrate(void *);
@@ -355,6 +359,7 @@
 		device_get_unit(sc->sc_dev));
 
 	callout_init(&sc->sc_calib_ch, CALLOUT_MPSAFE);
+	callout_init(&sc->sc_amrr_ch, CALLOUT_MPSAFE);
 
 	ifp->if_softc = sc;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
@@ -428,8 +433,13 @@
 	ic->ic_scan_start = bwi_scan_start;
 	ic->ic_scan_end = bwi_scan_end;
 	ic->ic_set_channel = bwi_set_channel;
+	ic->ic_node_alloc = bwi_node_alloc;
+	ic->ic_newassoc = bwi_newassoc;
 	/* complete initialization */
 	ieee80211_media_init(ic, bwi_media_change, ieee80211_media_status);
+	ieee80211_amrr_init(&sc->sc_amrr, ic,
+	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
+	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD);
 
 	/*
 	 * Attach radio tap
@@ -462,6 +472,7 @@
 	int i;
 
 	bwi_stop(sc);
+	callout_stop(&sc->sc_amrr_ch);
 	ieee80211_ifdetach(&sc->sc_ic);
 
 	for (i = 0; i < sc->sc_nmac; ++i)
@@ -1207,14 +1218,11 @@
 		struct ieee80211_frame *wh;
 		struct ieee80211_node *ni;
 		struct mbuf *m;
-		int mgt_pkt = 0;
 
 		IF_DEQUEUE(&ic->ic_mgtq, m);
 		if (m != NULL) {
 			ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
 			m->m_pkthdr.rcvif = NULL;
-
-			mgt_pkt = 1;
 		} else {
 			struct ether_header *eh;
 
@@ -1267,11 +1275,6 @@
 		}
 		wh = NULL;	/* Catch any invalid use */
 
-		if (mgt_pkt) {
-			ieee80211_free_node(ni);
-			ni = NULL;
-		}
-
 		if (bwi_encap(sc, idx, m, ni) != 0) {
 			/* 'm' is freed in bwi_encap() if we reach here */
 			if (ni != NULL)
@@ -1520,6 +1523,7 @@
 	BWI_LOCK(sc);
 
 	callout_stop(&sc->sc_calib_ch);
+	callout_stop(&sc->sc_amrr_ch);
 
 	if (nstate == IEEE80211_S_INIT)
 		goto back;
@@ -1537,6 +1541,11 @@
 
 		/* Initial TX power calibration */
 		bwi_mac_calibrate_txpower(mac);
+
+		/* start automatic rate control timer */
+		if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
+			callout_reset(&sc->sc_amrr_ch, hz / 2,
+			    bwi_amrr_timeout, sc);
 	} else {
 		bwi_set_bssid(sc, bwi_zero_addr);
 	}
@@ -1553,6 +1562,56 @@
 	return error;
 }
 
+/* ARGUSED */
+static struct ieee80211_node *
+bwi_node_alloc(struct ieee80211_node_table *nt __unused)
+{
+	struct bwi_node *bn;
+
+	bn = malloc(sizeof(struct bwi_node), M_80211_NODE, M_NOWAIT | M_ZERO);
+	return bn != NULL ? &bn->ni : NULL;
+}
+
+static void
+bwi_newassoc(struct ieee80211_node *ni, int isnew)
+{
+	struct bwi_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+	int i;
+
+	ieee80211_amrr_node_init(&sc->sc_amrr, &((struct bwi_node *)ni)->amn);
+
+	/* set rate to some reasonable initial value */
+	for (i = ni->ni_rates.rs_nrates - 1;
+	     i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
+	     i--);
+	ni->ni_txrate = i;
+}
+
+static void
+bwi_iter_func(void *arg, struct ieee80211_node *ni)
+{
+	struct bwi_softc *sc = arg;
+	struct bwi_node *bn = (struct bwi_node *)ni;
+
+	ieee80211_amrr_choose(&sc->sc_amrr, ni, &bn->amn);
+}
+
+static void
+bwi_amrr_timeout(void *arg)
+{
+	struct bwi_softc *sc = arg;
+	struct ieee80211com *ic = &sc->sc_ic;
+
+	BWI_LOCK(sc);
+	if (ic->ic_opmode == IEEE80211_M_STA)
+		bwi_iter_func(sc, ic->ic_bss);
+	else
+		ieee80211_iterate_nodes(&ic->ic_sta, bwi_iter_func, sc);
+	BWI_UNLOCK(sc);
+
+	callout_reset(&sc->sc_amrr_ch, hz / 2, bwi_amrr_timeout, sc);
+}
+
 static int
 bwi_media_change(struct ifnet *ifp)
 {
@@ -2736,28 +2795,15 @@
 	 * Find TX rate
 	 */
 	bzero(tb->tb_rate_idx, sizeof(tb->tb_rate_idx));
-	if (ni != NULL) {
-		if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
-			/* NB: no fallback */
-			rate = rate_fb = ic->ic_fixed_rate;
-		} else {
-			/* TODO: TX rate control */
-			rate = rate_fb = (1 * 2);
-		}
-	} else {
-		/* Fixed at 1Mbits/s for mgt frames */
-		rate = rate_fb = (1 * 2);
-	}
-
 	if (IEEE80211_IS_MULTICAST(wh->i_addr1))
 		rate = rate_fb = ic->ic_mcast_rate;
+	else if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
+		rate = ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL;
+		rate_fb = (ni->ni_txrate > 0) ?
+		   ni->ni_rates.rs_rates[ni->ni_txrate-1] & IEEE80211_RATE_VAL : rate;
+	} else
+		rate = rate_fb = ic->ic_fixed_rate;
 
-	if (rate == 0 || rate_fb == 0) {
-		if_printf(ic->ic_ifp, "invalid rate %u or fallback rate %u",
-			  rate, rate_fb);
-		rate = rate_fb = (1 * 2); /* Force 1Mbits/s */
-	}
-
 	/*
 	 * TX radio tap
 	 */
@@ -2790,14 +2836,14 @@
 	bcopy(wh->i_fc, hdr->txh_fc, sizeof(hdr->txh_fc));
 	bcopy(wh->i_addr1, hdr->txh_addr1, sizeof(hdr->txh_addr1));
 
-	if (ni != NULL && !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
 		uint16_t dur;
 		uint8_t ack_rate;
 
 		ack_rate = ieee80211_ack_rate(ni, rate_fb);
 		dur = ieee80211_txtime(ni,
-		sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN,
-		ack_rate, ic->ic_flags & ~IEEE80211_F_SHPREAMBLE);
+		    sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN,
+		    ack_rate, ic->ic_flags & ~IEEE80211_F_SHPREAMBLE);
 
 		hdr->txh_fb_duration = htole16(dur);
 	}
@@ -2940,6 +2986,7 @@
 	struct bwi_txbuf_data *tbd;
 	struct bwi_txbuf *tb;
 	int ring_idx, buf_idx;
+	struct ieee80211_node *ni;
 
 	if (tx_id == 0) {
 		if_printf(ifp, "zero tx id\n");
@@ -2966,14 +3013,30 @@
 	tb = &tbd->tbd_buf[buf_idx];
 
 	bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap);
-	m_freem(tb->tb_mbuf);
-	tb->tb_mbuf = NULL;
 
+	ni = tb->tb_ni;
 	if (tb->tb_ni != NULL) {
+		struct bwi_node *bn = (struct bwi_node *) tb->tb_ni;
+
+		/* XXX only for unicast frames */
 		/* Feed back 'acked and data_txcnt' */
+		if (acked)
+			bn->amn.amn_success++;
+		bn->amn.amn_txcnt++;
+		bn->amn.amn_retrycnt += data_txcnt-1;
+
+		/*
+		 * Do any tx complete callback.  Note this must
+		 * be done before releasing the node reference.
+		 */
+		if (tb->tb_mbuf->m_flags & M_TXCB)
+			ieee80211_process_callback(ni, tb->tb_mbuf, !acked);
+
 		ieee80211_free_node(tb->tb_ni);
 		tb->tb_ni = NULL;
 	}
+	m_freem(tb->tb_mbuf);
+	tb->tb_mbuf = NULL;
 
 	if (tbd->tbd_used == 0)
 		sc->sc_tx_timer = 0;

==== //depot/projects/wifi/sys/dev/bwi/if_bwi_pci.c#2 (text+ko) ====

@@ -55,6 +55,7 @@
 
 #include <net80211/ieee80211_var.h>
 #include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_amrr.h>
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
@@ -285,3 +286,4 @@
 MODULE_VERSION(if_bwi, 1);
 MODULE_DEPEND(if_bwi, wlan, 1, 1, 1);		/* 802.11 media layer */
 MODULE_DEPEND(if_bwi, firmware, 1, 1, 1);	/* firmware support */
+MODULE_DEPEND(if_bwi, wlan_amrr, 1, 1, 1);

==== //depot/projects/wifi/sys/dev/bwi/if_bwivar.h#2 (text+ko) ====

@@ -488,9 +488,15 @@
 	/* TODO: sq */
 };
 
+struct bwi_node {
+	struct ieee80211_node		ni;	/* must be the first */
+	struct ieee80211_amrr_node	amn;
+};
+
 struct bwi_softc {
 	struct ifnet		*sc_ifp;
 	struct ieee80211com	sc_ic;
+	struct ieee80211_amrr	sc_amrr;
 	uint32_t		sc_flags;	/* BWI_F_ */
 	device_t		sc_dev;
 	struct mtx		sc_mtx;
@@ -520,6 +526,7 @@
 	bus_space_handle_t	sc_mem_bh;
 
 	struct callout		sc_calib_ch;
+	struct callout		sc_amrr_ch;
 
 	struct bwi_regwin	*sc_cur_regwin;
 	struct bwi_regwin	sc_com_regwin;



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