PERFORCE change 135207 for review

Sepherosa Ziehau sephe at FreeBSD.org
Mon Feb 11 02:43:12 PST 2008


http://perforce.freebsd.org/chv.cgi?CH=135207

Change 135207 by sephe at sephe_zealot:sam_wifi on 2008/02/11 10:43:04

	- Build rate table when STA is going to associate BSS, the
	  calculation is according to the BSS's basic rate set.
	- Set ic_currates to ic_dynrates if operating as STA and 802.11
	  state machine has ticked to RUN.
	
	How to handle rate table when NIC operates in IBSS mode is not
	clear to me yet (starter of IBSS does not need to calculate rate
	table dynamicly, while as a member of IBSS, dynamic calculation
	should be done)
	HT, half and quarter dynamic rate table setting up need more work,
	now default HT, half and quarter rate tables are simply duplicated.

Affected files ...

.. //depot/projects/wifi/sys/net80211/ieee80211.c#64 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#91 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_node.c#100 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_phy.c#9 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_phy.h#5 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_proto.c#66 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_scan.c#21 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_var.h#66 edit

Differences ...

==== //depot/projects/wifi/sys/net80211/ieee80211.c#64 (text+ko) ====

@@ -295,6 +295,7 @@
 	ieee80211_crypto_detach(ic);
 	ieee80211_power_detach(ic);
 	ieee80211_node_detach(ic);
+	ieee80211_phy_detach(ic);
 	ifmedia_removeall(&ic->ic_media);
 
 	IEEE80211_LOCK_DESTROY(ic);
@@ -1234,8 +1235,11 @@
 }
 
 void
-ieee80211_set_channel(struct ieee80211com *ic, struct ieee80211_channel *c)
+ieee80211_set_channel(struct ieee80211com *ic, struct ieee80211_channel *c,
+    int dynrt)
 {
 	ieee80211_update_curchan(ic, c);
+	if (dynrt && ic->ic_dynrates != NULL)
+		ic->ic_currates = ic->ic_dynrates;
 	ic->ic_set_channel(ic);
 }

==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#91 (text+ko) ====

@@ -1758,7 +1758,7 @@
 		 * Monitor and wds modes can switch directly.
 		 */
 		if (ic->ic_state == IEEE80211_S_RUN)
-			ieee80211_set_channel(ic, ic->ic_des_chan);
+			ieee80211_set_channel(ic, ic->ic_des_chan, 0);
 		else
 			ieee80211_update_curchan(ic, ic->ic_des_chan);
 	} else {

==== //depot/projects/wifi/sys/net80211/ieee80211_node.c#100 (text+ko) ====

@@ -40,6 +40,7 @@
 #include <net/ethernet.h>
 
 #include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_phy.h>
 
 #include <net/bpf.h>
 
@@ -541,9 +542,17 @@
 void
 ieee80211_setbsschan(struct ieee80211com *ic, struct ieee80211_channel *c)
 {
+	int dynrt = 0;
+
 	ic->ic_bsschan = c;
 	ic->ic_curmode = ieee80211_chan2mode(ic->ic_bsschan);
-	ieee80211_set_channel(ic, ic->ic_bsschan);
+
+	ieee80211_free_dynratetable(ic);
+	if (ic->ic_opmode == IEEE80211_M_STA /* XXX IBSS */) {
+		ieee80211_set_dynratetable(ic, ic->ic_bsschan);
+		dynrt = 1;
+	}
+	ieee80211_set_channel(ic, ic->ic_bsschan, dynrt);
 }
 
 /*

==== //depot/projects/wifi/sys/net80211/ieee80211_phy.c#9 (text+ko) ====

@@ -552,3 +552,131 @@
 	}
 	return txTime;
 }
+
+void
+ieee80211_free_dynratetable(struct ieee80211com *ic)
+{
+	if (ic->ic_dynrates != NULL) {
+		if (ic->ic_currates == ic->ic_dynrates) {
+			/*
+			 * If ic_currates shadows ic_dynrates,
+			 * reset it to the default rate table
+			 * of the current channel.
+			 */
+			ic->ic_currates =
+				ieee80211_get_ratetable(ic->ic_curchan);
+		}
+
+		free(ic->ic_dynrates, M_DEVBUF /* XXX */);
+		ic->ic_dynrates = NULL;
+	}
+}
+
+/* XXX */
+#define IEEE80211_T_PBCC	(IEEE80211_T_HT + 1)
+
+void
+ieee80211_set_dynratetable(struct ieee80211com *ic,
+    const struct ieee80211_channel *c)
+{
+	const struct ieee80211_rate_table *rt0;
+	const struct ieee80211_rateset *rs;
+	struct ieee80211_rate_table *rt;
+	int i, cck = -1, ofdm = -1;
+
+	ieee80211_free_dynratetable(ic);
+
+	rt = malloc(sizeof(*rt), M_DEVBUF, M_NOWAIT | M_ZERO);
+	if (rt == NULL)
+		return;
+	ic->ic_dynrates = rt;
+
+	/* XXX HT, half and quarter */
+	rt0 = NULL;
+	if (IEEE80211_IS_CHAN_HALF(c))
+		rt0 = &ieee80211_half_table;
+	else if (IEEE80211_IS_CHAN_QUARTER(c))
+		rt0 = &ieee80211_quarter_table;
+	else if (IEEE80211_IS_CHAN_HTA(c))
+		rt0 = &ieee80211_11a_table;
+	else if (IEEE80211_IS_CHAN_HTG(c))
+		rt0 = &ieee80211_11g_table;
+	if (rt0 != NULL) {
+		bcopy(rt0, rt, sizeof(rt));
+		return;
+	}
+
+	rs = &ic->ic_bss->ni_rates;
+	rt->rateCount = rs->rs_nrates;
+	KASSERT(rt->rateCount <= (sizeof(rt->info) / sizeof(rt->info[0])),
+		("oversized rate table\n"));
+	for (i = 0; i < rs->rs_nrates; ++i) {
+		uint8_t rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
+		int j;
+
+		if (rate == 44)
+			rt->info[i].phy = IEEE80211_T_PBCC;
+		else if (rate == 22 || rate < 12) {
+			rt->info[i].phy = IEEE80211_T_CCK;
+			if (rate != 2) {
+				/*
+				 * DS 1Mbps does not support
+				 * short preamble.
+				 */
+				rt->info[i].shortPreamble = 0x04;
+			}
+			/* All DS/CCK rates are considered mandatory */
+			cck = i;
+		} else {
+			rt->info[i].phy = IEEE80211_T_OFDM;
+
+			/* 6/12/24Mbps are OFDM mandatory rates */
+			if (rate == 12 || rate == 24 || rate == 48)
+				ofdm = i;
+		}
+
+		rt->info[i].dot11Rate = rs->rs_rates[i];
+		rt->info[i].rateKbps = rate * 500;
+
+		for (j = i; j >= 0; --j)
+			if (rt->info[j].phy == rt->info[i].phy &&
+			    (rt->info[j].dot11Rate & IEEE80211_RATE_BASIC)) {
+				/*
+				 * Basic rate and same PHY type
+				 */
+				rt->info[i].ctlRateIndex = j;
+				break;
+			}
+		if (j < 0) {
+			switch (rt->info[i].phy) {
+			case IEEE80211_T_CCK:
+				rt->info[i].ctlRateIndex = i;
+				break;
+			case IEEE80211_T_PBCC:
+				rt->info[i].ctlRateIndex = cck < 0 ? i : cck;
+				break;
+			case IEEE80211_T_OFDM:
+				rt->info[i].ctlRateIndex = ofdm < 0 ? i : ofdm;
+				break;
+			default:
+				panic("unknown phy %d\n", rt->info[i].phy);
+				break;
+			}
+		}
+	}
+	ieee80211_setup_ratetable(rt);
+
+	for (i = 0; i < rt->rateCount; ++i) {
+		printf("phy %d, rate 0x%02x %u, ctlIdx %d\n",
+		       rt->info[i].phy,
+		       rt->info[i].dot11Rate, rt->info[i].rateKbps,
+		       rt->info[i].ctlRateIndex);
+	}
+}
+
+void
+ieee80211_phy_detach(struct ieee80211com *ic)
+{
+	ic->ic_currates = NULL;
+	ieee80211_free_dynratetable(ic);
+}

==== //depot/projects/wifi/sys/net80211/ieee80211_phy.h#5 (text+ko) ====

@@ -30,14 +30,17 @@
 
 #ifdef _KERNEL
 
+struct ieee80211com;
 struct ieee80211_channel;
 struct ieee80211_rate_table;
 
-/* Initialization functions */
 void		ieee80211_phy_init(void);
+void		ieee80211_phy_detach(struct ieee80211com *);
 const struct ieee80211_rate_table *ieee80211_get_ratetable(
 			const struct ieee80211_channel *);
-
+void		ieee80211_free_dynratetable(struct ieee80211com *);
+void		ieee80211_set_dynratetable(struct ieee80211com *,
+			const struct ieee80211_channel *);
 uint16_t	ieee80211_ack_duration(const struct ieee80211_rate_table *,
 			uint8_t, int);
 uint16_t	ieee80211_compute_duration(const struct ieee80211_rate_table *,

==== //depot/projects/wifi/sys/net80211/ieee80211_proto.c#66 (text+ko) ====

@@ -44,6 +44,7 @@
 #include <net/ethernet.h>		/* XXX for ether_sprintf */
 
 #include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_phy.h>
 
 /* XXX tunables */
 #define	AGGRESSIVE_MODE_SWITCH_HYSTERESIS	3	/* pkts / 100ms */
@@ -937,6 +938,10 @@
 {
 	struct ieee80211_channel *chan;
 
+	KASSERT(ic->ic_opmode == IEEE80211_M_STA,
+		("dynamic turbo switching in non-STA opmode(%d)\n",
+		 ic->ic_opmode));
+
 	chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags);
 	if (chan == NULL) {		/* XXX should not happen */
 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG,
@@ -953,7 +958,9 @@
 
 	ic->ic_bsschan = chan;
 	ic->ic_prevchan = ic->ic_curchan;
-	ieee80211_set_channel(ic, chan);
+	ieee80211_free_dynratetable(ic);
+	ieee80211_set_dynratetable(ic, chan);
+	ieee80211_set_channel(ic, chan, 1);
 	/* NB: do not need to reset ERP state 'cuz we're in sta mode */
 }
 

==== //depot/projects/wifi/sys/net80211/ieee80211_scan.c#21 (text+ko) ====

@@ -734,7 +734,7 @@
 		/*
 		 * Potentially change channel and phy mode.
 		 */
-		ieee80211_set_channel(ic, chan);
+		ieee80211_set_channel(ic, chan, 0);
 
 		/*
 		 * Scan curchan.  Drivers for "intelligent hardware"
@@ -759,8 +759,11 @@
 			ic->ic_lastscan = ticks;
 		/* return to the bss channel */
 		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
-		    ic->ic_curchan != ic->ic_bsschan)
-			ieee80211_set_channel(ic, ic->ic_bsschan);
+		    ic->ic_curchan != ic->ic_bsschan) {
+			ieee80211_set_channel(ic, ic->ic_bsschan,
+			    ic->ic_opmode == IEEE80211_M_STA &&
+			    ic->ic_state == IEEE80211_S_RUN);
+		}
 		/* clear internal flags and any indication of a pick */
 		SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
 		ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK;

==== //depot/projects/wifi/sys/net80211/ieee80211_var.h#66 (text+ko) ====

@@ -148,6 +148,8 @@
 	uint8_t			ic_chan_scan[IEEE80211_CHAN_BYTES];
 						/* current channel ratetable */
 	const struct ieee80211_rate_table *ic_currates;
+						/* negociated rate table */
+	struct ieee80211_rate_table *ic_dynrates;
 	struct ieee80211_channel *ic_curchan;	/* current channel */
 	struct ieee80211_channel *ic_bsschan;	/* bss channel */
 	struct ieee80211_channel *ic_prevchan;	/* previous channel */
@@ -432,7 +434,7 @@
 int	ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
 enum ieee80211_phymode ieee80211_chan2mode(const struct ieee80211_channel *);
 void	ieee80211_set_channel(struct ieee80211com *,
-		struct ieee80211_channel *);
+		struct ieee80211_channel *, int);
 void	ieee80211_update_curchan(struct ieee80211com *,
 		struct ieee80211_channel *);
 


More information about the p4-projects mailing list