svn commit: r293716 - in head/sys/dev: iwn wpi

Andriy Voskoboinyk avos at FreeBSD.org
Tue Jan 12 00:24:42 UTC 2016


Author: avos
Date: Tue Jan 12 00:24:40 2016
New Revision: 293716
URL: https://svnweb.freebsd.org/changeset/base/293716

Log:
  wpi, iwn: implement ic_getradiocaps method
  
  This will allow to restore channel list after switching interface
  to more restrictive regdomain.
  
  Tested with Intel 3945BG (wpi) only.
  
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D4863

Modified:
  head/sys/dev/iwn/if_iwn.c
  head/sys/dev/wpi/if_wpi.c

Modified: head/sys/dev/iwn/if_iwn.c
==============================================================================
--- head/sys/dev/iwn/if_iwn.c	Tue Jan 12 00:20:57 2016	(r293715)
+++ head/sys/dev/iwn/if_iwn.c	Tue Jan 12 00:24:40 2016	(r293716)
@@ -177,11 +177,15 @@ static void	iwn4965_print_power_group(st
 #endif
 static void	iwn5000_read_eeprom(struct iwn_softc *);
 static uint32_t	iwn_eeprom_channel_flags(struct iwn_eeprom_chan *);
-static void	iwn_read_eeprom_band(struct iwn_softc *, int);
-static void	iwn_read_eeprom_ht40(struct iwn_softc *, int);
+static void	iwn_read_eeprom_band(struct iwn_softc *, int, int, int *,
+		    struct ieee80211_channel[]);
+static void	iwn_read_eeprom_ht40(struct iwn_softc *, int, int, int *,
+		    struct ieee80211_channel[]);
 static void	iwn_read_eeprom_channels(struct iwn_softc *, int, uint32_t);
 static struct iwn_eeprom_chan *iwn_find_eeprom_channel(struct iwn_softc *,
 		    struct ieee80211_channel *);
+static void	iwn_getradiocaps(struct ieee80211com *, int, int *,
+		    struct ieee80211_channel[]);
 static int	iwn_setregdomain(struct ieee80211com *,
 		    struct ieee80211_regdomain *, int,
 		    struct ieee80211_channel[]);
@@ -666,6 +670,7 @@ iwn_attach(device_t dev)
 	ic->ic_set_channel = iwn_set_channel;
 	ic->ic_scan_curchan = iwn_scan_curchan;
 	ic->ic_scan_mindwell = iwn_scan_mindwell;
+	ic->ic_getradiocaps = iwn_getradiocaps;
 	ic->ic_setregdomain = iwn_setregdomain;
 
 	iwn_radiotap_attach(sc);
@@ -2371,9 +2376,9 @@ iwn_eeprom_channel_flags(struct iwn_eepr
 }
 
 static void
-iwn_read_eeprom_band(struct iwn_softc *sc, int n)
+iwn_read_eeprom_band(struct iwn_softc *sc, int n, int maxchans, int *nchans,
+    struct ieee80211_channel chans[])
 {
-	struct ieee80211com *ic = &sc->sc_ic;
 	struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
 	const struct iwn_chan_band *band = &iwn_bands[n];
 	struct ieee80211_channel *c;
@@ -2390,10 +2395,14 @@ iwn_read_eeprom_band(struct iwn_softc *s
 			    channels[i].maxpwr);
 			continue;
 		}
+
+		if (*nchans >= maxchans)
+			break;
+
 		chan = band->chan[i];
 		nflags = iwn_eeprom_channel_flags(&channels[i]);
 
-		c = &ic->ic_channels[ic->ic_nchans++];
+		c = &chans[(*nchans)++];
 		c->ic_ieee = chan;
 		c->ic_maxregpower = channels[i].maxpwr;
 		c->ic_maxpower = 2*c->ic_maxregpower;
@@ -2402,7 +2411,11 @@ iwn_read_eeprom_band(struct iwn_softc *s
 			c->ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_G);
 			/* G =>'s B is supported */
 			c->ic_flags = IEEE80211_CHAN_B | nflags;
-			c = &ic->ic_channels[ic->ic_nchans++];
+
+			if (*nchans >= maxchans)
+				break;
+
+			c = &chans[(*nchans)++];
 			c[0] = c[-1];
 			c->ic_flags = IEEE80211_CHAN_G | nflags;
 		} else {	/* 5GHz band */
@@ -2418,8 +2431,11 @@ iwn_read_eeprom_band(struct iwn_softc *s
 		    channels[i].flags, channels[i].maxpwr);
 
 		if (sc->sc_flags & IWN_FLAG_HAS_11N) {
+			if (*nchans >= maxchans)
+				break;
+
 			/* add HT20, HT40 added separately */
-			c = &ic->ic_channels[ic->ic_nchans++];
+			c = &chans[(*nchans)++];
 			c[0] = c[-1];
 			c->ic_flags |= IEEE80211_CHAN_HT20;
 		}
@@ -2430,7 +2446,8 @@ iwn_read_eeprom_band(struct iwn_softc *s
 }
 
 static void
-iwn_read_eeprom_ht40(struct iwn_softc *sc, int n)
+iwn_read_eeprom_ht40(struct iwn_softc *sc, int n, int maxchans, int *nchans,
+    struct ieee80211_channel chans[])
 {
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
@@ -2454,6 +2471,10 @@ iwn_read_eeprom_ht40(struct iwn_softc *s
 			    channels[i].maxpwr);
 			continue;
 		}
+
+		if (*nchans + 1 >= maxchans)
+			break;
+
 		chan = band->chan[i];
 		nflags = iwn_eeprom_channel_flags(&channels[i]);
 
@@ -2481,12 +2502,12 @@ iwn_read_eeprom_ht40(struct iwn_softc *s
 		    "add ht40 chan %d flags 0x%x maxpwr %d\n",
 		    chan, channels[i].flags, channels[i].maxpwr);
 
-		c = &ic->ic_channels[ic->ic_nchans++];
+		c = &chans[(*nchans)++];
 		c[0] = cent[0];
 		c->ic_extieee = extc->ic_ieee;
 		c->ic_flags &= ~IEEE80211_CHAN_HT;
 		c->ic_flags |= IEEE80211_CHAN_HT40U | nflags;
-		c = &ic->ic_channels[ic->ic_nchans++];
+		c = &chans[(*nchans)++];
 		c[0] = extc[0];
 		c->ic_extieee = cent->ic_ieee;
 		c->ic_flags &= ~IEEE80211_CHAN_HT;
@@ -2505,10 +2526,13 @@ iwn_read_eeprom_channels(struct iwn_soft
 	iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n],
 	    iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan));
 
-	if (n < 5)
-		iwn_read_eeprom_band(sc, n);
-	else
-		iwn_read_eeprom_ht40(sc, n);
+	if (n < 5) {
+		iwn_read_eeprom_band(sc, n, IEEE80211_CHAN_MAX, &ic->ic_nchans,
+		    ic->ic_channels);
+	} else {
+		iwn_read_eeprom_ht40(sc, n, IEEE80211_CHAN_MAX, &ic->ic_nchans,
+		    ic->ic_channels);
+	}
 	ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans);
 }
 
@@ -2538,6 +2562,20 @@ iwn_find_eeprom_channel(struct iwn_softc
 	return NULL;
 }
 
+static void
+iwn_getradiocaps(struct ieee80211com *ic,
+    int maxchans, int *nchans, struct ieee80211_channel chans[])
+{
+	struct iwn_softc *sc = ic->ic_softc;
+	int i;
+
+	/* Parse the list of authorized channels. */
+	for (i = 0; i < 5 && *nchans < maxchans; i++)
+		iwn_read_eeprom_band(sc, i, maxchans, nchans, chans);
+	for (i = 5; i < IWN_NBANDS - 1 && *nchans < maxchans; i++)
+		iwn_read_eeprom_ht40(sc, i, maxchans, nchans, chans);
+}
+
 /*
  * Enforce flags read from EEPROM.
  */

Modified: head/sys/dev/wpi/if_wpi.c
==============================================================================
--- head/sys/dev/wpi/if_wpi.c	Tue Jan 12 00:20:57 2016	(r293715)
+++ head/sys/dev/wpi/if_wpi.c	Tue Jan 12 00:24:40 2016	(r293716)
@@ -166,10 +166,13 @@ static void	wpi_free_tx_ring(struct wpi_
 static int	wpi_read_eeprom(struct wpi_softc *,
 		    uint8_t macaddr[IEEE80211_ADDR_LEN]);
 static uint32_t	wpi_eeprom_channel_flags(struct wpi_eeprom_chan *);
-static void	wpi_read_eeprom_band(struct wpi_softc *, uint8_t);
+static void	wpi_read_eeprom_band(struct wpi_softc *, uint8_t, int, int *,
+		    struct ieee80211_channel[]);
 static int	wpi_read_eeprom_channels(struct wpi_softc *, uint8_t);
 static struct wpi_eeprom_chan *wpi_find_eeprom_channel(struct wpi_softc *,
 		    struct ieee80211_channel *);
+static void	wpi_getradiocaps(struct ieee80211com *, int, int *,
+		    struct ieee80211_channel[]);
 static int	wpi_setregdomain(struct ieee80211com *,
 		    struct ieee80211_regdomain *, int,
 		    struct ieee80211_channel[]);
@@ -516,6 +519,7 @@ wpi_attach(device_t dev)
 	ic->ic_set_channel = wpi_set_channel;
 	ic->ic_scan_curchan = wpi_scan_curchan;
 	ic->ic_scan_mindwell = wpi_scan_mindwell;
+	ic->ic_getradiocaps = wpi_getradiocaps;
 	ic->ic_setregdomain = wpi_setregdomain;
 
 	sc->sc_update_rx_ring = wpi_update_rx_ring;
@@ -1417,9 +1421,9 @@ wpi_eeprom_channel_flags(struct wpi_eepr
 }
 
 static void
-wpi_read_eeprom_band(struct wpi_softc *sc, uint8_t n)
+wpi_read_eeprom_band(struct wpi_softc *sc, uint8_t n, int maxchans,
+    int *nchans, struct ieee80211_channel chans[])
 {
-	struct ieee80211com *ic = &sc->sc_ic;
 	struct wpi_eeprom_chan *channels = sc->eeprom_channels[n];
 	const struct wpi_chan_band *band = &wpi_bands[n];
 	struct ieee80211_channel *c;
@@ -1434,10 +1438,13 @@ wpi_read_eeprom_band(struct wpi_softc *s
 			continue;
 		}
 
+		if (*nchans >= maxchans)
+			break;
+
 		chan = band->chan[i];
 		nflags = wpi_eeprom_channel_flags(&channels[i]);
 
-		c = &ic->ic_channels[ic->ic_nchans++];
+		c = &chans[(*nchans)++];
 		c->ic_ieee = chan;
 		c->ic_maxregpower = channels[i].maxpwr;
 		c->ic_maxpower = 2*c->ic_maxregpower;
@@ -1448,7 +1455,11 @@ wpi_read_eeprom_band(struct wpi_softc *s
 
 			/* G =>'s B is supported */
 			c->ic_flags = IEEE80211_CHAN_B | nflags;
-			c = &ic->ic_channels[ic->ic_nchans++];
+
+			if (*nchans >= maxchans)
+				break;
+
+			c = &chans[(*nchans)++];
 			c[0] = c[-1];
 			c->ic_flags = IEEE80211_CHAN_G | nflags;
 		} else {	/* 5GHz band */
@@ -1465,7 +1476,7 @@ wpi_read_eeprom_band(struct wpi_softc *s
 		    "adding chan %d (%dMHz) flags=0x%x maxpwr=%d passive=%d,"
 		    " offset %d\n", chan, c->ic_freq,
 		    channels[i].flags, sc->maxpwr[chan],
-		    IEEE80211_IS_CHAN_PASSIVE(c), ic->ic_nchans);
+		    IEEE80211_IS_CHAN_PASSIVE(c), *nchans);
 	}
 }
 
@@ -1489,7 +1500,8 @@ wpi_read_eeprom_channels(struct wpi_soft
 		return error;
 	}
 
-	wpi_read_eeprom_band(sc, n);
+	wpi_read_eeprom_band(sc, n, IEEE80211_CHAN_MAX, &ic->ic_nchans,
+	    ic->ic_channels);
 
 	ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans);
 
@@ -1511,6 +1523,18 @@ wpi_find_eeprom_channel(struct wpi_softc
 	return NULL;
 }
 
+static void
+wpi_getradiocaps(struct ieee80211com *ic,
+    int maxchans, int *nchans, struct ieee80211_channel chans[])
+{
+	struct wpi_softc *sc = ic->ic_softc;
+	int i;
+
+	/* Parse the list of authorized channels. */
+	for (i = 0; i < WPI_CHAN_BANDS_COUNT && *nchans < maxchans; i++)
+		wpi_read_eeprom_band(sc, i, maxchans, nchans, chans);
+}
+
 /*
  * Enforce flags read from EEPROM.
  */


More information about the svn-src-head mailing list