Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 28 Jan 2011 08:57:58 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r218013 - head/sys/dev/ath/ath_rate/sample
Message-ID:  <201101280857.p0S8vwLn068252@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Fri Jan 28 08:57:58 2011
New Revision: 218013
URL: http://svn.freebsd.org/changeset/base/218013

Log:
  (Mostly) teach ath_rate_sample about MCS rates.
  
  This is just the bare minimum needed to teach ath_rate_sample to try
  and handle MCS rates. It doesn't at all attempt to find the best
  rate by any means - it doesn't know anything about the MCS rate
  relations, TX aggregation or any of the much sexier 11n stuff
  that's out there.
  
  It's just enough to transmit 11n frames and handle TX completion.
  
  It shouldn't affect legacy (11abg) behaviour.
  
  Obtained from:	rpaulo@

Added:
  head/sys/dev/ath/ath_rate/sample/tx_schedules.h   (contents, props changed)
Modified:
  head/sys/dev/ath/ath_rate/sample/sample.c

Modified: head/sys/dev/ath/ath_rate/sample/sample.c
==============================================================================
--- head/sys/dev/ath/ath_rate/sample/sample.c	Fri Jan 28 08:45:19 2011	(r218012)
+++ head/sys/dev/ath/ath_rate/sample/sample.c	Fri Jan 28 08:57:58 2011	(r218013)
@@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ath/if_athvar.h>
 #include <dev/ath/ath_rate/sample/sample.h>
 #include <dev/ath/ath_hal/ah_desc.h>
+#include <dev/ath/ath_rate/sample/tx_schedules.h>
 
 /*
  * This file is an implementation of the SampleRate algorithm
@@ -142,6 +143,13 @@ ath_rate_node_cleanup(struct ath_softc *
 {
 }
 
+static int
+dot11rate(const HAL_RATE_TABLE *rt, int rix)
+{
+	return rt->info[rix].phy == IEEE80211_T_HT ?
+	    rt->info[rix].dot11Rate : (rt->info[rix].dot11Rate & IEEE80211_RATE_VAL) / 2;
+}
+
 /*
  * Return the rix with the lowest average_tx_time,
  * or -1 if all the average_tx_times are 0.
@@ -186,6 +194,7 @@ pick_sample_rate(struct sample_softc *ss
     const HAL_RATE_TABLE *rt, int size_bin)
 {
 #define	DOT11RATE(ix)	(rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
+#define	MCS(ix)		(rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
 	int current_rix, rix;
 	unsigned current_tt;
 	uint32_t mask;
@@ -232,6 +241,7 @@ pick_sample_rate(struct sample_softc *ss
 	}
 	return current_rix;
 #undef DOT11RATE
+#undef	MCS
 }
 
 void
@@ -240,6 +250,7 @@ ath_rate_findrate(struct ath_softc *sc, 
 		  u_int8_t *rix0, int *try0, u_int8_t *txrate)
 {
 #define	DOT11RATE(ix)	(rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
+#define	MCS(ix)		(rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
 #define	RATE(ix)	(DOT11RATE(ix) / 2)
 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
 	struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
@@ -334,7 +345,7 @@ ath_rate_findrate(struct ath_softc *sc, 
 			/* 
 			 * Set the visible txrate for this node.
 			 */
-			an->an_node.ni_txrate = DOT11RATE(best_rix);
+			an->an_node.ni_txrate = (rt->info[best_rix].phy == IEEE80211_T_HT) ?  MCS(best_rix) : DOT11RATE(best_rix);
 		}
 		rix = sn->current_rix[size_bin];
 		sn->packets_since_switch[size_bin]++;
@@ -348,81 +359,10 @@ done:
 		| (shortPreamble ? rt->info[rix].shortPreamble : 0);
 	sn->packets_sent[size_bin]++;
 #undef DOT11RATE
+#undef MCS
 #undef RATE
 }
 
-#define A(_r) \
-    (((_r) == 6)   ? 0 : (((_r) == 9)   ? 1 : (((_r) == 12)  ? 2 : \
-    (((_r) == 18)  ? 3 : (((_r) == 24)  ? 4 : (((_r) == 36)  ? 5 : \
-    (((_r) == 48)  ? 6 : (((_r) == 54)  ? 7 : 0))))))))
-static const struct txschedule series_11a[] = {
-	{ 3,A( 6), 3,A(  6), 0,A(  6), 0,A( 6) },	/*   6Mb/s */
-	{ 4,A( 9), 3,A(  6), 4,A(  6), 0,A( 6) },	/*   9Mb/s */
-	{ 4,A(12), 3,A(  6), 4,A(  6), 0,A( 6) },	/*  12Mb/s */
-	{ 4,A(18), 3,A( 12), 4,A(  6), 2,A( 6) },	/*  18Mb/s */
-	{ 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) },	/*  24Mb/s */
-	{ 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) },	/*  36Mb/s */
-	{ 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) },	/*  48Mb/s */
-	{ 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) }	/*  54Mb/s */
-};
-#undef A
-
-#define G(_r) \
-    (((_r) == 1)   ? 0 : (((_r) == 2)   ? 1 : (((_r) == 5.5) ? 2 : \
-    (((_r) == 11)  ? 3 : (((_r) == 6)   ? 4 : (((_r) == 9)   ? 5 : \
-    (((_r) == 12)  ? 6 : (((_r) == 18)  ? 7 : (((_r) == 24)  ? 8 : \
-    (((_r) == 36)  ? 9 : (((_r) == 48)  ? 10 : (((_r) == 54)  ? 11 : 0))))))))))))
-static const struct txschedule series_11g[] = {
-	{ 3,G( 1), 3,G(  1), 0,G(  1), 0,G( 1) },	/*   1Mb/s */
-	{ 4,G( 2), 3,G(  1), 4,G(  1), 0,G( 1) },	/*   2Mb/s */
-	{ 4,G(5.5),3,G(  2), 4,G(  1), 2,G( 1) },	/* 5.5Mb/s */
-	{ 4,G(11), 3,G(5.5), 4,G(  2), 2,G( 1) },	/*  11Mb/s */
-	{ 4,G( 6), 3,G(5.5), 4,G(  2), 2,G( 1) },	/*   6Mb/s */
-	{ 4,G( 9), 3,G(  6), 4,G(5.5), 2,G( 1) },	/*   9Mb/s */
-	{ 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) },	/*  12Mb/s */
-	{ 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) },	/*  18Mb/s */
-	{ 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) },	/*  24Mb/s */
-	{ 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) },	/*  36Mb/s */
-	{ 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) },	/*  48Mb/s */
-	{ 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) }	/*  54Mb/s */
-};
-#undef G
-
-#define H(_r) \
-    (((_r) == 3)   ? 0 : (((_r) == 4.5) ? 1 : (((_r) == 6)  ? 2 : \
-    (((_r) == 9)   ? 3 : (((_r) == 12)  ? 4 : (((_r) == 18) ? 5 : \
-    (((_r) == 24)  ? 6 : (((_r) == 27)  ? 7 : 0))))))))
-static const struct txschedule series_half[] = {
-	{ 3,H( 3), 3,H(  3), 0,H(  3), 0,H( 3) },	/*   3Mb/s */
-	{ 4,H(4.5),3,H(  3), 4,H(  3), 0,H( 3) },	/* 4.5Mb/s */
-	{ 4,H( 6), 3,H(  3), 4,H(  3), 0,H( 3) },	/*   6Mb/s */
-	{ 4,H( 9), 3,H(  6), 4,H(  3), 2,H( 3) },	/*   9Mb/s */
-	{ 4,H(12), 3,H(  9), 4,H(  6), 2,H( 3) },	/*  12Mb/s */
-	{ 4,H(18), 3,H( 12), 4,H(  9), 2,H( 3) },	/*  18Mb/s */
-	{ 4,H(24), 3,H( 18), 4,H( 12), 2,H( 6) },	/*  24Mb/s */
-	{ 4,H(27), 3,H( 24), 4,H( 18), 2,H(12) }	/*  27Mb/s */
-};
-#undef H
-
-#ifdef Q
-#undef Q		/* sun4v bogosity */
-#endif
-#define Q(_r) \
-    (((_r) == 1.5) ? 0 : (((_r) ==2.25) ? 1 : (((_r) == 3)  ? 2 : \
-    (((_r) == 4.5) ? 3 : (((_r) ==  6)  ? 4 : (((_r) == 9)  ? 5 : \
-    (((_r) == 12)  ? 6 : (((_r) == 13.5)? 7 : 0))))))))
-static const struct txschedule series_quarter[] = {
-	{ 3,Q( 1.5),3,Q(1.5), 0,Q(1.5), 0,Q(1.5) },	/* 1.5Mb/s */
-	{ 4,Q(2.25),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) },	/*2.25Mb/s */
-	{ 4,Q(   3),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) },	/*   3Mb/s */
-	{ 4,Q( 4.5),3,Q(  3), 4,Q(1.5), 2,Q(1.5) },	/* 4.5Mb/s */
-	{ 4,Q(   6),3,Q(4.5), 4,Q(  3), 2,Q(1.5) },	/*   6Mb/s */
-	{ 4,Q(   9),3,Q(  6), 4,Q(4.5), 2,Q(1.5) },	/*   9Mb/s */
-	{ 4,Q(  12),3,Q(  9), 4,Q(  6), 2,Q(  3) },	/*  12Mb/s */
-	{ 4,Q(13.5),3,Q( 12), 4,Q(  9), 2,Q(  6) }	/*13.5Mb/s */
-};
-#undef Q
-
 void
 ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
 		      struct ath_desc *ds, int shortPreamble, u_int8_t rix)
@@ -592,7 +532,7 @@ ath_rate_tx_complete(struct ath_softc *s
 		     __func__,
 		     bin_to_size(size_to_bin(frame_size)),
 		     ts->ts_status ? "FAIL" : "OK",
-		     final_rix, short_tries, long_tries);
+		     dot11rate(rt, final_rix), short_tries, long_tries);
 		update_stats(sc, an, frame_size, 
 			     final_rix, long_tries,
 			     0, 0,
@@ -608,8 +548,10 @@ ath_rate_tx_complete(struct ath_softc *s
 		 * Process intermediate rates that failed.
 		 */
 		ath_hal_gettxcompletionrates(sc->sc_ah, ds0, hwrates, tries);
-		for (i = 0; i < 4; i++)
+
+		for (i = 0; i < 4; i++) {
 			rix[i] = rt->rateCodeToIndex[hwrates[i]];
+		}
 
 		IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
 		    &an->an_node,
@@ -619,19 +561,15 @@ ath_rate_tx_complete(struct ath_softc *s
 		     finalTSIdx,
 		     long_tries, 
 		     ts->ts_status ? "FAIL" : "OK",
-		     rix[0], tries[0],
-		     rix[1], tries[1],
-		     rix[2], tries[2],
-		     rix[3], tries[3]);
-
-		if (tries[0] && !IS_RATE_DEFINED(sn, rix[0]))
-			badrate(ifp, 0, hwrates[0], tries[0], ts->ts_status);
-		if (tries[1] && !IS_RATE_DEFINED(sn, rix[1]))
-			badrate(ifp, 1, hwrates[1], tries[1], ts->ts_status);
-		if (tries[2] && !IS_RATE_DEFINED(sn, rix[2]))
-			badrate(ifp, 2, hwrates[2], tries[2], ts->ts_status);
-		if (tries[3] && !IS_RATE_DEFINED(sn, rix[3]))
-			badrate(ifp, 3, hwrates[3], tries[3], ts->ts_status);
+		     dot11rate(rt, rix[0]), tries[0],
+		     dot11rate(rt, rix[1]), tries[1],
+		     dot11rate(rt, rix[2]), tries[2],
+		     dot11rate(rt, rix[3]), tries[3]);
+
+		for (i = 0; i < 4; i++) {
+			if (tries[i] && !IS_RATE_DEFINED(sn, rix[i]))
+				badrate(ifp, 0, hwrates[i], tries[i], ts->ts_status);
+		}
 
 		/*
 		 * NB: series > 0 are not penalized for failure
@@ -675,7 +613,7 @@ ath_rate_tx_complete(struct ath_softc *s
 
 		if (tries[3] && finalTSIdx > 2) {
 			update_stats(sc, an, frame_size, 
-				     rix[3], tries[3], 
+				     rix[3], tries[3],
 				     0, 0,
 				     0, 0,
 				     0, 0,
@@ -701,8 +639,8 @@ static const struct txschedule *mrr_sche
 	series_11a,	/* IEEE80211_MODE_TURBO_A */
 	series_11g,	/* IEEE80211_MODE_TURBO_G */
 	series_11a,	/* IEEE80211_MODE_STURBO_A */
-	series_11a,	/* IEEE80211_MODE_11NA */
-	series_11g,	/* IEEE80211_MODE_11NG */
+	series_11na,	/* IEEE80211_MODE_11NA */
+	series_11ng,	/* IEEE80211_MODE_11NG */
 	series_half,	/* IEEE80211_MODE_HALF */
 	series_quarter,	/* IEEE80211_MODE_QUARTER */
 };
@@ -715,6 +653,8 @@ ath_rate_ctl_reset(struct ath_softc *sc,
 {
 #define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
 #define	DOT11RATE(_ix)	(rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
+#define	MCS(_ix)	(ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
+
 	struct ath_node *an = ATH_NODE(ni);
 	const struct ieee80211_txparam *tp = ni->ni_txparms;
 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
@@ -737,8 +677,11 @@ ath_rate_ctl_reset(struct ath_softc *sc,
 		 * negotiated rate set for the node.  Note the fixed rate
 		 * may not be available for various reasons so we only
 		 * setup the static rate index if the lookup is successful.
-		 * XXX handle MCS
 		 */
+
+		/* XXX todo: check MCS rates */
+
+		/* Check legacy rates */
 		for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--)
 			if (RATE(srate) == tp->ucastrate) {
 				sn->static_rix = sc->sc_rixmap[tp->ucastrate];
@@ -761,6 +704,22 @@ ath_rate_ctl_reset(struct ath_softc *sc,
 	 * to be ignored for doing rate control.
 	 */
 	sn->ratemask = 0;
+	/* MCS rates */
+	if (ni->ni_flags & IEEE80211_NODE_HT) {
+		for (x = 0; x < ni->ni_htrates.rs_nrates; x++) {
+			rix = sc->sc_rixmap[MCS(x)];
+			if (rix == 0xff)
+				continue;
+			/* skip rates marked broken by hal */
+			if (!rt->info[rix].valid)
+				continue;
+			KASSERT(rix < SAMPLE_MAXRATES,
+			    ("mcs %u has rix %d", MCS(x), rix));
+			sn->ratemask |= 1<<rix;
+		}
+	}
+
+	/* Legacy rates */
 	for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
 		rix = sc->sc_rixmap[RATE(x)];
 		if (rix == 0xff)
@@ -781,7 +740,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
 		for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
 			if ((mask & 1) == 0)
 				continue;
-			printf(" %d/%d", DOT11RATE(rix) / 2,
+			printf(" %d/%d", dot11rate(rt, rix),
 			    calc_usecs_unicast_packet(sc, 1600, rix, 0,0));
 		}
 		printf("\n");
@@ -866,7 +825,7 @@ sample_stats(void *arg, struct ieee80211
 			if (sn->stats[y][rix].total_packets == 0)
 				continue;
 			printf("[%2u:%4u] %8d:%-8d (%3d%%) T %8d F %4d avg %5u last %u\n",
-			    (rt->info[rix].dot11Rate & IEEE80211_RATE_VAL)/2,
+			    dot11rate(rt, rix),
 			    bin_to_size(y),
 			    sn->stats[y][rix].total_packets,
 			    sn->stats[y][rix].packets_acked,

Added: head/sys/dev/ath/ath_rate/sample/tx_schedules.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/ath/ath_rate/sample/tx_schedules.h	Fri Jan 28 08:57:58 2011	(r218013)
@@ -0,0 +1,193 @@
+/*-
+ * Copyright (c) 2005 John Bicket
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+#ifndef	__ATH_RATE_SAMPLE_TXSCHEDULES_H__
+#define	__ATH_RATE_SAMPLE_TXSCHEDULES_H__
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define A(_r) \
+    (((_r) == 6)   ? 0 : (((_r) == 9)   ? 1 : (((_r) == 12)  ? 2 : \
+    (((_r) == 18)  ? 3 : (((_r) == 24)  ? 4 : (((_r) == 36)  ? 5 : \
+    (((_r) == 48)  ? 6 : (((_r) == 54)  ? 7 : 0))))))))
+static const struct txschedule series_11a[] = {
+	{ 3,A( 6), 3,A(  6), 0,A(  6), 0,A( 6) },	/*   6Mb/s */
+	{ 4,A( 9), 3,A(  6), 4,A(  6), 0,A( 6) },	/*   9Mb/s */
+	{ 4,A(12), 3,A(  6), 4,A(  6), 0,A( 6) },	/*  12Mb/s */
+	{ 4,A(18), 3,A( 12), 4,A(  6), 2,A( 6) },	/*  18Mb/s */
+	{ 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) },	/*  24Mb/s */
+	{ 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) },	/*  36Mb/s */
+	{ 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) },	/*  48Mb/s */
+	{ 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) }	/*  54Mb/s */
+};
+
+#define NA1(_r) \
+	(((_r) == 6.5)  ? 8 : (((_r) == 13)  ?  9 : (((_r) == 19.5)? 10 : \
+	(((_r) == 26)  ? 11 : (((_r) == 39)  ? 12 : (((_r) == 52)  ? 13 : \
+	(((_r) == 58.5)? 14 : (((_r) == 65)  ? 15 : 0))))))))
+#define NA2(_r) \
+	(((_r) == 13) ? 16 : (((_r) == 26) ? 17 : (((_r) == 39) ? 18 : \
+	(((_r) == 52) ? 19 : (((_r) == 78) ? 20 : (((_r) == 104)? 21 : \
+	(((_r) == 117)? 22 : (((_r) == 130)? 23 : 0))))))))
+static const struct txschedule series_11na[] = {
+	{ 3,A( 6), 3,A(  6), 0,A(  6), 0,A( 6) },       /*   6Mb/s */
+	{ 4,A( 9), 3,A(  6), 4,A(  6), 0,A( 6) },       /*   9Mb/s */
+	{ 4,A(12), 3,A(  6), 4,A(  6), 0,A( 6) },       /*  12Mb/s */
+	{ 4,A(18), 3,A( 12), 4,A(  6), 2,A( 6) },       /*  18Mb/s */
+	{ 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) },       /*  24Mb/s */
+	{ 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) },       /*  36Mb/s */
+	{ 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) },       /*  48Mb/s */
+	{ 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) },       /*  54Mb/s */
+	{ 3,NA1( 6.5), 3,NA1( 6.5), 0,NA1( 6.5), 0,NA1(6.5) },  /* 6.5Mb/s */
+	{ 4,NA1(  13), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) },  /*  13Mb/s */
+	{ 4,NA1(19.5), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) },  /*19.5Mb/s */
+	{ 4,NA1(  26), 3,NA1(19.5), 4,NA1( 6.5), 2,NA1(6.5) },  /*  26Mb/s */
+	{ 4,NA1(  39), 3,NA1(  26), 4,NA1(19.5), 2,NA1(6.5) },  /*  39Mb/s */
+	{ 4,NA1(  52), 3,NA1(  39), 4,NA1(  26), 2,NA1(6.5) },  /*  52Mb/s */
+	{ 4,NA1(58.5), 3,NA1(  52), 4,NA1(  39), 2,NA1( 13) },  /*58.5Mb/s */
+	{ 4,NA1(  65), 3,NA1(58.5), 4,NA1(  52), 2,NA1( 13) },  /*  65Mb/s */
+	{ 3,NA2(  13), 3,NA2(  13), 0,NA2(  13), 0,NA2( 13) },  /*  13Mb/s */
+	{ 4,NA2(  26), 3,NA2(  13), 4,NA2(  13), 0,NA2( 13) },  /*  26Mb/s */
+	{ 4,NA2(  39), 3,NA2(  26), 4,NA2(  13), 2,NA2( 13) },  /*  39Mb/s */
+	{ 4,NA2(  52), 3,NA2(  39), 4,NA2(  26), 2,NA2( 13) },  /*  52Mb/s */
+	{ 4,NA2(  78), 3,NA2(  52), 4,NA2(  39), 2,NA2( 13) },  /*  78Mb/s */
+	{ 4,NA2( 104), 3,NA2(  78), 4,NA2(  52), 2,NA2( 13) },  /* 104Mb/s */
+	{ 4,NA2( 117), 3,NA2( 104), 4,NA2(  78), 2,NA2( 26) },  /* 117Mb/s */
+	{ 4,NA2( 130), 3,NA2( 117), 4,NA2( 104), 2,NA2( 26) }   /* 130Mb/s */
+};
+#undef A
+#undef NA2
+#undef NA1
+
+#define G(_r) \
+    (((_r) == 1)   ? 0 : (((_r) == 2)   ? 1 : (((_r) == 5.5) ? 2 : \
+    (((_r) == 11)  ? 3 : (((_r) == 6)   ? 4 : (((_r) == 9)   ? 5 : \
+    (((_r) == 12)  ? 6 : (((_r) == 18)  ? 7 : (((_r) == 24)  ? 8 : \
+    (((_r) == 36)  ? 9 : (((_r) == 48)  ? 10 : (((_r) == 54)  ? 11 : 0))))))))))))
+static const struct txschedule series_11g[] = {
+	{ 3,G( 1), 3,G(  1), 0,G(  1), 0,G( 1) },	/*   1Mb/s */
+	{ 4,G( 2), 3,G(  1), 4,G(  1), 0,G( 1) },	/*   2Mb/s */
+	{ 4,G(5.5),3,G(  2), 4,G(  1), 2,G( 1) },	/* 5.5Mb/s */
+	{ 4,G(11), 3,G(5.5), 4,G(  2), 2,G( 1) },	/*  11Mb/s */
+	{ 4,G( 6), 3,G(5.5), 4,G(  2), 2,G( 1) },	/*   6Mb/s */
+	{ 4,G( 9), 3,G(  6), 4,G(5.5), 2,G( 1) },	/*   9Mb/s */
+	{ 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) },	/*  12Mb/s */
+	{ 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) },	/*  18Mb/s */
+	{ 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) },	/*  24Mb/s */
+	{ 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) },	/*  36Mb/s */
+	{ 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) },	/*  48Mb/s */
+	{ 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) }	/*  54Mb/s */
+};
+
+#define NG1(_r) \
+	(((_r) == 6.5) ? 12 : (((_r) == 13) ? 13 : (((_r) == 19.5)? 14 : \
+	(((_r) == 26)  ? 15 : (((_r) == 39) ? 16 : (((_r) == 52)  ? 17 : \
+	(((_r) == 58.5)? 18 : (((_r) == 65) ? 19 : 0))))))))
+#define NG2(_r) \
+	(((_r) == 13)  ? 20 : (((_r) == 26) ? 21 : (((_r) == 39)  ? 22 : \
+	(((_r) == 52)  ? 23 : (((_r) == 78) ? 24 : (((_r) == 104) ? 25 : \
+	(((_r) == 117) ? 26 : (((_r) == 130)? 27 : 0))))))))
+static const struct txschedule series_11ng[] = {
+	{ 3,G( 1), 3,G(  1), 0,G(  1), 0,G( 1) },       /*   1Mb/s */
+	{ 4,G( 2), 3,G(  1), 4,G(  1), 0,G( 1) },       /*   2Mb/s */
+	{ 4,G(5.5),3,G(  2), 4,G(  1), 2,G( 1) },       /* 5.5Mb/s */
+	{ 4,G(11), 3,G(5.5), 4,G(  2), 2,G( 1) },       /*  11Mb/s */
+	{ 4,G( 6), 3,G(5.5), 4,G(  2), 2,G( 1) },       /*   6Mb/s */
+	{ 4,G( 9), 3,G(  6), 4,G(5.5), 2,G( 1) },       /*   9Mb/s */
+	{ 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) },       /*  12Mb/s */
+	{ 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) },       /*  18Mb/s */
+	{ 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) },       /*  24Mb/s */
+	{ 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) },       /*  36Mb/s */
+	{ 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) },       /*  48Mb/s */
+	{ 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) },       /*  54Mb/s */
+	{ 3,NG1( 6.5), 3,NG1( 6.5), 0,NG1( 6.5), 0,NG1(6.5) },  /* 6.5Mb/s */
+	{ 4,NG1(  13), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) },  /*  13Mb/s */
+	{ 4,NG1(19.5), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) },  /*19.5Mb/s */
+	{ 4,NG1(  26), 3,NG1(19.5), 4,NG1( 6.5), 2,NG1(6.5) },  /*  26Mb/s */
+	{ 4,NG1(  39), 3,NG1(  26), 4,NG1(19.5), 2,NG1(6.5) },  /*  39Mb/s */
+	{ 4,NG1(  52), 3,NG1(  39), 4,NG1(  26), 2,NG1(6.5) },  /*  52Mb/s */
+	{ 4,NG1(58.5), 3,NG1(  52), 4,NG1(  39), 2,NG1( 13) },  /*58.5Mb/s */
+	{ 4,NG1(  65), 3,NG1(58.5), 4,NG1(  52), 2,NG1( 13) },  /*  65Mb/s */
+	{ 3,NG2(  13), 3,NG2(  13), 0,NG2(  13), 0,NG2( 13) },  /*  13Mb/s */
+	{ 4,NG2(  26), 3,NG2(  13), 4,NG2(  13), 0,NG2( 13) },  /*  26Mb/s */
+	{ 4,NG2(  39), 3,NG2(  26), 4,NG2(  13), 2,NG2( 13) },  /*  39Mb/s */
+	{ 4,NG2(  52), 3,NG2(  39), 4,NG2(  26), 2,NG2( 13) },  /*  52Mb/s */
+	{ 4,NG2(  78), 3,NG2(  52), 4,NG2(  39), 2,NG2( 13) },  /*  78Mb/s */
+	{ 4,NG2( 104), 3,NG2(  78), 4,NG2(  52), 2,NG2( 13) },  /* 104Mb/s */
+	{ 4,NG2( 117), 3,NG2( 104), 4,NG2(  78), 2,NG2( 26) },  /* 117Mb/s */
+	{ 4,NG2( 130), 3,NG2( 117), 4,NG2( 104), 2,NG2( 26) }   /* 130Mb/s */
+};
+#undef G
+#undef NG2
+#undef NG1
+
+#define H(_r) \
+    (((_r) == 3)   ? 0 : (((_r) == 4.5) ? 1 : (((_r) == 6)  ? 2 : \
+    (((_r) == 9)   ? 3 : (((_r) == 12)  ? 4 : (((_r) == 18) ? 5 : \
+    (((_r) == 24)  ? 6 : (((_r) == 27)  ? 7 : 0))))))))
+static const struct txschedule series_half[] = {
+	{ 3,H( 3), 3,H(  3), 0,H(  3), 0,H( 3) },	/*   3Mb/s */
+	{ 4,H(4.5),3,H(  3), 4,H(  3), 0,H( 3) },	/* 4.5Mb/s */
+	{ 4,H( 6), 3,H(  3), 4,H(  3), 0,H( 3) },	/*   6Mb/s */
+	{ 4,H( 9), 3,H(  6), 4,H(  3), 2,H( 3) },	/*   9Mb/s */
+	{ 4,H(12), 3,H(  9), 4,H(  6), 2,H( 3) },	/*  12Mb/s */
+	{ 4,H(18), 3,H( 12), 4,H(  9), 2,H( 3) },	/*  18Mb/s */
+	{ 4,H(24), 3,H( 18), 4,H( 12), 2,H( 6) },	/*  24Mb/s */
+	{ 4,H(27), 3,H( 24), 4,H( 18), 2,H(12) }	/*  27Mb/s */
+};
+#undef H
+
+#ifdef Q
+#undef Q		/* sun4v bogosity */
+#endif
+#define Q(_r) \
+    (((_r) == 1.5) ? 0 : (((_r) ==2.25) ? 1 : (((_r) == 3)  ? 2 : \
+    (((_r) == 4.5) ? 3 : (((_r) ==  6)  ? 4 : (((_r) == 9)  ? 5 : \
+    (((_r) == 12)  ? 6 : (((_r) == 13.5)? 7 : 0))))))))
+static const struct txschedule series_quarter[] = {
+	{ 3,Q( 1.5),3,Q(1.5), 0,Q(1.5), 0,Q(1.5) },	/* 1.5Mb/s */
+	{ 4,Q(2.25),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) },	/*2.25Mb/s */
+	{ 4,Q(   3),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) },	/*   3Mb/s */
+	{ 4,Q( 4.5),3,Q(  3), 4,Q(1.5), 2,Q(1.5) },	/* 4.5Mb/s */
+	{ 4,Q(   6),3,Q(4.5), 4,Q(  3), 2,Q(1.5) },	/*   6Mb/s */
+	{ 4,Q(   9),3,Q(  6), 4,Q(4.5), 2,Q(1.5) },	/*   9Mb/s */
+	{ 4,Q(  12),3,Q(  9), 4,Q(  6), 2,Q(  3) },	/*  12Mb/s */
+	{ 4,Q(13.5),3,Q( 12), 4,Q(  9), 2,Q(  6) }	/*13.5Mb/s */
+};
+#undef Q
+
+#endif



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