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
This commit is contained in:
parent
c16d674c2d
commit
1c6b43df0a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=293716
@ -177,11 +177,15 @@ static void iwn4965_print_power_group(struct iwn_softc *, int);
|
|||||||
#endif
|
#endif
|
||||||
static void iwn5000_read_eeprom(struct iwn_softc *);
|
static void iwn5000_read_eeprom(struct iwn_softc *);
|
||||||
static uint32_t iwn_eeprom_channel_flags(struct iwn_eeprom_chan *);
|
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_band(struct iwn_softc *, int, int, int *,
|
||||||
static void iwn_read_eeprom_ht40(struct iwn_softc *, 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 void iwn_read_eeprom_channels(struct iwn_softc *, int, uint32_t);
|
||||||
static struct iwn_eeprom_chan *iwn_find_eeprom_channel(struct iwn_softc *,
|
static struct iwn_eeprom_chan *iwn_find_eeprom_channel(struct iwn_softc *,
|
||||||
struct ieee80211_channel *);
|
struct ieee80211_channel *);
|
||||||
|
static void iwn_getradiocaps(struct ieee80211com *, int, int *,
|
||||||
|
struct ieee80211_channel[]);
|
||||||
static int iwn_setregdomain(struct ieee80211com *,
|
static int iwn_setregdomain(struct ieee80211com *,
|
||||||
struct ieee80211_regdomain *, int,
|
struct ieee80211_regdomain *, int,
|
||||||
struct ieee80211_channel[]);
|
struct ieee80211_channel[]);
|
||||||
@ -666,6 +670,7 @@ iwn_attach(device_t dev)
|
|||||||
ic->ic_set_channel = iwn_set_channel;
|
ic->ic_set_channel = iwn_set_channel;
|
||||||
ic->ic_scan_curchan = iwn_scan_curchan;
|
ic->ic_scan_curchan = iwn_scan_curchan;
|
||||||
ic->ic_scan_mindwell = iwn_scan_mindwell;
|
ic->ic_scan_mindwell = iwn_scan_mindwell;
|
||||||
|
ic->ic_getradiocaps = iwn_getradiocaps;
|
||||||
ic->ic_setregdomain = iwn_setregdomain;
|
ic->ic_setregdomain = iwn_setregdomain;
|
||||||
|
|
||||||
iwn_radiotap_attach(sc);
|
iwn_radiotap_attach(sc);
|
||||||
@ -2371,9 +2376,9 @@ iwn_eeprom_channel_flags(struct iwn_eeprom_chan *channel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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];
|
struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
|
||||||
const struct iwn_chan_band *band = &iwn_bands[n];
|
const struct iwn_chan_band *band = &iwn_bands[n];
|
||||||
struct ieee80211_channel *c;
|
struct ieee80211_channel *c;
|
||||||
@ -2390,10 +2395,14 @@ iwn_read_eeprom_band(struct iwn_softc *sc, int n)
|
|||||||
channels[i].maxpwr);
|
channels[i].maxpwr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*nchans >= maxchans)
|
||||||
|
break;
|
||||||
|
|
||||||
chan = band->chan[i];
|
chan = band->chan[i];
|
||||||
nflags = iwn_eeprom_channel_flags(&channels[i]);
|
nflags = iwn_eeprom_channel_flags(&channels[i]);
|
||||||
|
|
||||||
c = &ic->ic_channels[ic->ic_nchans++];
|
c = &chans[(*nchans)++];
|
||||||
c->ic_ieee = chan;
|
c->ic_ieee = chan;
|
||||||
c->ic_maxregpower = channels[i].maxpwr;
|
c->ic_maxregpower = channels[i].maxpwr;
|
||||||
c->ic_maxpower = 2*c->ic_maxregpower;
|
c->ic_maxpower = 2*c->ic_maxregpower;
|
||||||
@ -2402,7 +2411,11 @@ iwn_read_eeprom_band(struct iwn_softc *sc, int n)
|
|||||||
c->ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_G);
|
c->ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_G);
|
||||||
/* G =>'s B is supported */
|
/* G =>'s B is supported */
|
||||||
c->ic_flags = IEEE80211_CHAN_B | nflags;
|
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[0] = c[-1];
|
||||||
c->ic_flags = IEEE80211_CHAN_G | nflags;
|
c->ic_flags = IEEE80211_CHAN_G | nflags;
|
||||||
} else { /* 5GHz band */
|
} else { /* 5GHz band */
|
||||||
@ -2418,8 +2431,11 @@ iwn_read_eeprom_band(struct iwn_softc *sc, int n)
|
|||||||
channels[i].flags, channels[i].maxpwr);
|
channels[i].flags, channels[i].maxpwr);
|
||||||
|
|
||||||
if (sc->sc_flags & IWN_FLAG_HAS_11N) {
|
if (sc->sc_flags & IWN_FLAG_HAS_11N) {
|
||||||
|
if (*nchans >= maxchans)
|
||||||
|
break;
|
||||||
|
|
||||||
/* add HT20, HT40 added separately */
|
/* add HT20, HT40 added separately */
|
||||||
c = &ic->ic_channels[ic->ic_nchans++];
|
c = &chans[(*nchans)++];
|
||||||
c[0] = c[-1];
|
c[0] = c[-1];
|
||||||
c->ic_flags |= IEEE80211_CHAN_HT20;
|
c->ic_flags |= IEEE80211_CHAN_HT20;
|
||||||
}
|
}
|
||||||
@ -2430,7 +2446,8 @@ iwn_read_eeprom_band(struct iwn_softc *sc, int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 ieee80211com *ic = &sc->sc_ic;
|
||||||
struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
|
struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
|
||||||
@ -2454,6 +2471,10 @@ iwn_read_eeprom_ht40(struct iwn_softc *sc, int n)
|
|||||||
channels[i].maxpwr);
|
channels[i].maxpwr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*nchans + 1 >= maxchans)
|
||||||
|
break;
|
||||||
|
|
||||||
chan = band->chan[i];
|
chan = band->chan[i];
|
||||||
nflags = iwn_eeprom_channel_flags(&channels[i]);
|
nflags = iwn_eeprom_channel_flags(&channels[i]);
|
||||||
|
|
||||||
@ -2481,12 +2502,12 @@ iwn_read_eeprom_ht40(struct iwn_softc *sc, int n)
|
|||||||
"add ht40 chan %d flags 0x%x maxpwr %d\n",
|
"add ht40 chan %d flags 0x%x maxpwr %d\n",
|
||||||
chan, channels[i].flags, channels[i].maxpwr);
|
chan, channels[i].flags, channels[i].maxpwr);
|
||||||
|
|
||||||
c = &ic->ic_channels[ic->ic_nchans++];
|
c = &chans[(*nchans)++];
|
||||||
c[0] = cent[0];
|
c[0] = cent[0];
|
||||||
c->ic_extieee = extc->ic_ieee;
|
c->ic_extieee = extc->ic_ieee;
|
||||||
c->ic_flags &= ~IEEE80211_CHAN_HT;
|
c->ic_flags &= ~IEEE80211_CHAN_HT;
|
||||||
c->ic_flags |= IEEE80211_CHAN_HT40U | nflags;
|
c->ic_flags |= IEEE80211_CHAN_HT40U | nflags;
|
||||||
c = &ic->ic_channels[ic->ic_nchans++];
|
c = &chans[(*nchans)++];
|
||||||
c[0] = extc[0];
|
c[0] = extc[0];
|
||||||
c->ic_extieee = cent->ic_ieee;
|
c->ic_extieee = cent->ic_ieee;
|
||||||
c->ic_flags &= ~IEEE80211_CHAN_HT;
|
c->ic_flags &= ~IEEE80211_CHAN_HT;
|
||||||
@ -2505,10 +2526,13 @@ iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr)
|
|||||||
iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n],
|
iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n],
|
||||||
iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan));
|
iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan));
|
||||||
|
|
||||||
if (n < 5)
|
if (n < 5) {
|
||||||
iwn_read_eeprom_band(sc, n);
|
iwn_read_eeprom_band(sc, n, IEEE80211_CHAN_MAX, &ic->ic_nchans,
|
||||||
else
|
ic->ic_channels);
|
||||||
iwn_read_eeprom_ht40(sc, n);
|
} 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);
|
ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2538,6 +2562,20 @@ iwn_find_eeprom_channel(struct iwn_softc *sc, struct ieee80211_channel *c)
|
|||||||
return NULL;
|
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.
|
* Enforce flags read from EEPROM.
|
||||||
*/
|
*/
|
||||||
|
@ -166,10 +166,13 @@ static void wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
|
|||||||
static int wpi_read_eeprom(struct wpi_softc *,
|
static int wpi_read_eeprom(struct wpi_softc *,
|
||||||
uint8_t macaddr[IEEE80211_ADDR_LEN]);
|
uint8_t macaddr[IEEE80211_ADDR_LEN]);
|
||||||
static uint32_t wpi_eeprom_channel_flags(struct wpi_eeprom_chan *);
|
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 int wpi_read_eeprom_channels(struct wpi_softc *, uint8_t);
|
||||||
static struct wpi_eeprom_chan *wpi_find_eeprom_channel(struct wpi_softc *,
|
static struct wpi_eeprom_chan *wpi_find_eeprom_channel(struct wpi_softc *,
|
||||||
struct ieee80211_channel *);
|
struct ieee80211_channel *);
|
||||||
|
static void wpi_getradiocaps(struct ieee80211com *, int, int *,
|
||||||
|
struct ieee80211_channel[]);
|
||||||
static int wpi_setregdomain(struct ieee80211com *,
|
static int wpi_setregdomain(struct ieee80211com *,
|
||||||
struct ieee80211_regdomain *, int,
|
struct ieee80211_regdomain *, int,
|
||||||
struct ieee80211_channel[]);
|
struct ieee80211_channel[]);
|
||||||
@ -516,6 +519,7 @@ wpi_attach(device_t dev)
|
|||||||
ic->ic_set_channel = wpi_set_channel;
|
ic->ic_set_channel = wpi_set_channel;
|
||||||
ic->ic_scan_curchan = wpi_scan_curchan;
|
ic->ic_scan_curchan = wpi_scan_curchan;
|
||||||
ic->ic_scan_mindwell = wpi_scan_mindwell;
|
ic->ic_scan_mindwell = wpi_scan_mindwell;
|
||||||
|
ic->ic_getradiocaps = wpi_getradiocaps;
|
||||||
ic->ic_setregdomain = wpi_setregdomain;
|
ic->ic_setregdomain = wpi_setregdomain;
|
||||||
|
|
||||||
sc->sc_update_rx_ring = wpi_update_rx_ring;
|
sc->sc_update_rx_ring = wpi_update_rx_ring;
|
||||||
@ -1417,9 +1421,9 @@ wpi_eeprom_channel_flags(struct wpi_eeprom_chan *channel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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];
|
struct wpi_eeprom_chan *channels = sc->eeprom_channels[n];
|
||||||
const struct wpi_chan_band *band = &wpi_bands[n];
|
const struct wpi_chan_band *band = &wpi_bands[n];
|
||||||
struct ieee80211_channel *c;
|
struct ieee80211_channel *c;
|
||||||
@ -1434,10 +1438,13 @@ wpi_read_eeprom_band(struct wpi_softc *sc, uint8_t n)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*nchans >= maxchans)
|
||||||
|
break;
|
||||||
|
|
||||||
chan = band->chan[i];
|
chan = band->chan[i];
|
||||||
nflags = wpi_eeprom_channel_flags(&channels[i]);
|
nflags = wpi_eeprom_channel_flags(&channels[i]);
|
||||||
|
|
||||||
c = &ic->ic_channels[ic->ic_nchans++];
|
c = &chans[(*nchans)++];
|
||||||
c->ic_ieee = chan;
|
c->ic_ieee = chan;
|
||||||
c->ic_maxregpower = channels[i].maxpwr;
|
c->ic_maxregpower = channels[i].maxpwr;
|
||||||
c->ic_maxpower = 2*c->ic_maxregpower;
|
c->ic_maxpower = 2*c->ic_maxregpower;
|
||||||
@ -1448,7 +1455,11 @@ wpi_read_eeprom_band(struct wpi_softc *sc, uint8_t n)
|
|||||||
|
|
||||||
/* G =>'s B is supported */
|
/* G =>'s B is supported */
|
||||||
c->ic_flags = IEEE80211_CHAN_B | nflags;
|
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[0] = c[-1];
|
||||||
c->ic_flags = IEEE80211_CHAN_G | nflags;
|
c->ic_flags = IEEE80211_CHAN_G | nflags;
|
||||||
} else { /* 5GHz band */
|
} else { /* 5GHz band */
|
||||||
@ -1465,7 +1476,7 @@ wpi_read_eeprom_band(struct wpi_softc *sc, uint8_t n)
|
|||||||
"adding chan %d (%dMHz) flags=0x%x maxpwr=%d passive=%d,"
|
"adding chan %d (%dMHz) flags=0x%x maxpwr=%d passive=%d,"
|
||||||
" offset %d\n", chan, c->ic_freq,
|
" offset %d\n", chan, c->ic_freq,
|
||||||
channels[i].flags, sc->maxpwr[chan],
|
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_softc *sc, uint8_t n)
|
|||||||
return error;
|
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);
|
ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans);
|
||||||
|
|
||||||
@ -1511,6 +1523,18 @@ wpi_find_eeprom_channel(struct wpi_softc *sc, struct ieee80211_channel *c)
|
|||||||
return NULL;
|
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.
|
* Enforce flags read from EEPROM.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user