svn commit: r187841 - head/sbin/ifconfig

Sam Leffler sam at FreeBSD.org
Wed Jan 28 11:15:54 PST 2009


Author: sam
Date: Wed Jan 28 19:15:52 2009
New Revision: 187841
URL: http://svn.freebsd.org/changeset/base/187841

Log:
  Fix 1/2 and 1/4 width channel handling:
  o only include 1/2 and 1/4 width channels when they are specified in the
    regulatory database description; previously we treated them as if they
    were part of the band and blindly added them for 11a/g
  o check the channel list returned in the devcaps to identify whether a
    device supports 1/2 or 1/4 width channels on a band; this might be
    better brought out as a capability bit to avoid filling the channel
    list w/ 1/2 and 1/4 width channels but then cards that only support
    these channels in a range of frequencies could not be described (though
    right now we don't check frequency range only band)

Modified:
  head/sbin/ifconfig/ifieee80211.c

Modified: head/sbin/ifconfig/ifieee80211.c
==============================================================================
--- head/sbin/ifconfig/ifieee80211.c	Wed Jan 28 19:09:49 2009	(r187840)
+++ head/sbin/ifconfig/ifieee80211.c	Wed Jan 28 19:15:52 2009	(r187841)
@@ -1789,6 +1789,19 @@ chanlookup(const struct ieee80211_channe
 	return NULL;
 }
 
+static int
+chanfind(const struct ieee80211_channel chans[], int nchans, int flags)
+{
+	int i;
+
+	for (i = 0; i < nchans; i++) {
+		const struct ieee80211_channel *c = &chans[i];
+		if ((c->ic_flags & flags) == flags)
+			return 1;
+	}
+	return 0;
+}
+
 static void
 regdomain_addchans(struct ieee80211req_chaninfo *ci,
 	const netband_head *bands,
@@ -1799,9 +1812,15 @@ regdomain_addchans(struct ieee80211req_c
 	const struct netband *nb;
 	const struct freqband *b;
 	struct ieee80211_channel *c, *prev;
-	int freq, channelSep;
+	int freq, channelSep, hasHalfChans, hasQuarterChans;
 
 	channelSep = (chanFlags & IEEE80211_CHAN_2GHZ) ? 0 : 40;
+	hasHalfChans = chanfind(avail->ic_chans, avail->ic_nchans,
+	    IEEE80211_CHAN_HALF |
+	       (chanFlags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ)));
+	hasQuarterChans = chanfind(avail->ic_chans, avail->ic_nchans,
+	    IEEE80211_CHAN_QUARTER |
+	        (chanFlags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ)));
 	LIST_FOREACH(nb, bands, next) {
 		b = nb->band;
 		if (verbose)
@@ -1812,28 +1831,31 @@ regdomain_addchans(struct ieee80211req_c
 			uint32_t flags = nb->flags | b->flags;
 
 			/* check if device can operate on this frequency */
-			if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, chanFlags) == NULL) {
+			/*
+			 * XXX GSM frequency mapping is handled in the kernel
+			 * so we cannot find them in the calibration table;
+			 * just construct the list and the kernel will reject
+			 * if it's wrong.
+			 */
+			if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, chanFlags) == NULL &&
+			    (flags & IEEE80211_CHAN_GSM) == 0) {
 				if (verbose)
 					printf("%u: skip, flags 0x%x not available\n", freq, chanFlags);
 				continue;
 			}
-			/*
-			 * NB: don't enforce 1/2 and 1/4 rate channels being
-			 * specified in the device's calibration list for
-			 * 900MHz cards because most are not self-identifying.
-			 */
-			if ((flags & IEEE80211_CHAN_HALF) &&
-			    ((chanFlags & IEEE80211_CHAN_HALF) == 0 &&
-			     (flags & IEEE80211_CHAN_GSM) == 0)) {
+			if ((flags & IEEE80211_CHAN_HALF) && !hasHalfChans) {
 				if (verbose)
-					printf("%u: skip, device does not support half-rate channels\n", freq);
+					printf("%u: skip, device does not "
+					    "support half-rate channel\n",
+					    freq);
 				continue;
 			}
 			if ((flags & IEEE80211_CHAN_QUARTER) &&
-			    ((chanFlags & IEEE80211_CHAN_QUARTER) == 0 &&
-			     (flags & IEEE80211_CHAN_GSM) == 0)) {
+			    !hasQuarterChans) {
 				if (verbose)
-					printf("%u: skip, device does not support quarter-rate channels\n", freq);
+					printf("%u: skip, device does not "
+					    "support quarter-rate channel\n",
+					    freq);
 				continue;
 			}
 			if ((flags & IEEE80211_CHAN_HT20) &&
@@ -1932,26 +1954,12 @@ regdomain_makechannels(
 		if (!LIST_EMPTY(&rd->bands_11b))
 			regdomain_addchans(ci, &rd->bands_11b, reg,
 			    IEEE80211_CHAN_B, &dc->dc_chaninfo);
-		if (!LIST_EMPTY(&rd->bands_11g)) {
+		if (!LIST_EMPTY(&rd->bands_11g))
 			regdomain_addchans(ci, &rd->bands_11g, reg,
 			    IEEE80211_CHAN_G, &dc->dc_chaninfo);
-			regdomain_addchans(ci, &rd->bands_11g, reg,
-			    IEEE80211_CHAN_G | IEEE80211_CHAN_HALF,
-			    &dc->dc_chaninfo);
-			regdomain_addchans(ci, &rd->bands_11g, reg,
-			    IEEE80211_CHAN_G | IEEE80211_CHAN_QUARTER,
-			    &dc->dc_chaninfo);
-		}
-		if (!LIST_EMPTY(&rd->bands_11a)) {
+		if (!LIST_EMPTY(&rd->bands_11a))
 			regdomain_addchans(ci, &rd->bands_11a, reg,
 			    IEEE80211_CHAN_A, &dc->dc_chaninfo);
-			regdomain_addchans(ci, &rd->bands_11a, reg,
-			    IEEE80211_CHAN_A | IEEE80211_CHAN_HALF,
-			    &dc->dc_chaninfo);
-			regdomain_addchans(ci, &rd->bands_11a, reg,
-			    IEEE80211_CHAN_A | IEEE80211_CHAN_QUARTER,
-			    &dc->dc_chaninfo);
-		}
 		if (!LIST_EMPTY(&rd->bands_11na)) {
 			regdomain_addchans(ci, &rd->bands_11na, reg,
 			    IEEE80211_CHAN_A | IEEE80211_CHAN_HT20,


More information about the svn-src-head mailing list