Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src-draft/trunk]: src/sys/dev/pci Get supported channel list from NVM.
details: https://anonhg.NetBSD.org/src-all/rev/2bd71240df78
branches: trunk
changeset: 952646:2bd71240df78
user: Martin Husemann <martin%NetBSD.org@localhost>
date: Mon Jan 18 20:08:02 2021 +0100
description:
Get supported channel list from NVM.
diffstat:
sys/dev/pci/if_iwm.c | 218 +++++++++++++++++++++++------------------------
sys/dev/pci/if_iwmreg.h | 4 +-
sys/dev/pci/if_iwmvar.h | 5 +
3 files changed, 113 insertions(+), 114 deletions(-)
diffs (truncated from 338 to 300 lines):
diff -r 400cc3f7b5c3 -r 2bd71240df78 sys/dev/pci/if_iwm.c
--- a/sys/dev/pci/if_iwm.c Mon Jan 18 11:45:37 2021 +0100
+++ b/sys/dev/pci/if_iwm.c Mon Jan 18 20:08:02 2021 +0100
@@ -175,6 +175,7 @@
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
149, 153, 157, 161, 165
};
+CTASSERT(__arraycount(iwm_nvm_channels) <= IWM_MAX_CHANNELS);
static const uint8_t iwm_nvm_channels_8000[] = {
/* 2.4 GHz */
@@ -184,6 +185,7 @@
96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
149, 153, 157, 161, 165, 169, 173, 177, 181
};
+CTASSERT(__arraycount(iwm_nvm_channels_8000) <= IWM_MAX_CHANNELS);
#define IWM_NUM_2GHZ_CHANNELS 14
@@ -315,8 +317,6 @@
uint16_t, uint8_t *, uint16_t *);
static int iwm_nvm_read_section(struct iwm_softc *, uint16_t, uint8_t *,
uint16_t *, size_t);
-static void iwm_init_channel_map(struct iwm_softc *, const uint16_t * const,
- const uint8_t *, size_t);
static struct ieee80211vap *
iwm_vap_create(struct ieee80211com *,
const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
@@ -2668,72 +2668,101 @@
return rx_ant;
}
+/*
+ * Translate EEPROM flags to net80211.
+ */
+static uint32_t
+iwm_eeprom_channel_flags(uint16_t ch_flags)
+{
+ uint32_t nflags;
+
+ nflags = 0;
+ if ((ch_flags & IWM_NVM_CHANNEL_ACTIVE) == 0)
+ nflags |= IEEE80211_CHAN_PASSIVE;
+ if ((ch_flags & IWM_NVM_CHANNEL_IBSS) == 0)
+ nflags |= IEEE80211_CHAN_NOADHOC;
+ if (ch_flags & IWM_NVM_CHANNEL_RADAR) {
+ nflags |= IEEE80211_CHAN_DFS;
+ /* Just in case. */
+ nflags |= IEEE80211_CHAN_NOADHOC;
+ }
+
+ return nflags;
+}
+
static void
-iwm_init_channel_map(struct iwm_softc *sc, const uint16_t * const nvm_ch_flags,
- const uint8_t *nvm_channels, size_t nchan)
-{
- struct ieee80211com *ic = &sc->sc_ic;
- struct iwm_nvm_data *data = &sc->sc_nvm;
- int ch_idx;
- struct ieee80211_channel *channel;
+iwm_add_channel_band(struct iwm_softc *sc, struct ieee80211_channel chans[],
+ int maxchans, int *nchans, int ch_idx, size_t ch_num,
+ const uint8_t bands[])
+{
+ const uint16_t * const nvm_ch_flags = sc->sc_nvm.nvm_ch_flags;
+ uint32_t nflags;
uint16_t ch_flags;
- int is_5ghz;
- int flags, hw_value;
-
- for (ch_idx = 0; ch_idx < nchan; ch_idx++) {
+ uint8_t ieee;
+ int error;
+
+ for (; ch_idx < ch_num; ch_idx++) {
ch_flags = le16_to_cpup(nvm_ch_flags + ch_idx);
- aprint_debug_dev(sc->sc_dev,
- "Ch. %d: %svalid %cibss %s %cradar %cdfs"
- " %cwide %c40MHz %c80MHz %c160MHz\n",
- nvm_channels[ch_idx],
- ch_flags & IWM_NVM_CHANNEL_VALID ? "" : "in",
- ch_flags & IWM_NVM_CHANNEL_IBSS ? '+' : '-',
- ch_flags & IWM_NVM_CHANNEL_ACTIVE ? "active" : "passive",
- ch_flags & IWM_NVM_CHANNEL_RADAR ? '+' : '-',
- ch_flags & IWM_NVM_CHANNEL_DFS ? '+' : '-',
- ch_flags & IWM_NVM_CHANNEL_WIDE ? '+' : '-',
- ch_flags & IWM_NVM_CHANNEL_40MHZ ? '+' : '-',
- ch_flags & IWM_NVM_CHANNEL_80MHZ ? '+' : '-',
- ch_flags & IWM_NVM_CHANNEL_160MHZ ? '+' : '-');
-
- if (ch_idx >= IWM_NUM_2GHZ_CHANNELS &&
- !data->sku_cap_band_52GHz_enable)
- ch_flags &= ~IWM_NVM_CHANNEL_VALID;
+ if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)
+ ieee = iwm_nvm_channels[ch_idx];
+ else
+ ieee = iwm_nvm_channels_8000[ch_idx];
if (!(ch_flags & IWM_NVM_CHANNEL_VALID)) {
- DPRINTF(("Ch. %d Flags %x [%sGHz] - No traffic\n",
- nvm_channels[ch_idx], ch_flags,
- (ch_idx >= IWM_NUM_2GHZ_CHANNELS) ? "5" : "2.4"));
+ DPRINTFN(4,
+ ("Ch. %d Flags %x [%sGHz] - No traffic\n",
+ ieee, ch_flags,
+ (ch_idx >= IWM_NUM_2GHZ_CHANNELS) ?
+ "5.2" : "2.4"));
continue;
}
- hw_value = nvm_channels[ch_idx];
- channel = &ic->ic_channels[hw_value];
-
- is_5ghz = ch_idx >= IWM_NUM_2GHZ_CHANNELS;
- if (!is_5ghz) {
- flags = IEEE80211_CHAN_2GHZ;
- channel->ic_flags
- = IEEE80211_CHAN_CCK
- | IEEE80211_CHAN_OFDM
- | IEEE80211_CHAN_DYN
- | IEEE80211_CHAN_2GHZ;
- } else {
- flags = IEEE80211_CHAN_5GHZ;
- channel->ic_flags =
- IEEE80211_CHAN_A;
- }
- channel->ic_freq = ieee80211_ieee2mhz(hw_value, flags);
-
- if (!(ch_flags & IWM_NVM_CHANNEL_ACTIVE))
- channel->ic_flags |= IEEE80211_CHAN_PASSIVE;
-
-#ifndef IEEE80211_NO_HT
- if (data->sku_cap_11n_enable)
- channel->ic_flags |= IEEE80211_CHAN_HT;
-#endif
- }
-}
+ nflags = iwm_eeprom_channel_flags(ch_flags);
+ error = ieee80211_add_channel(chans, maxchans, nchans,
+ ieee, 0, 0, nflags, bands);
+ if (error != 0)
+ break;
+
+ DPRINTFN(4,
+ ("Ch. %d Flags %x [%sGHz] - Added\n",
+ ieee, ch_flags,
+ (ch_idx >= IWM_NUM_2GHZ_CHANNELS) ?
+ "5.2" : "2.4"));
+ }
+}
+
+static void
+iwm_get_radiocaps(struct ieee80211com *ic,
+ int maxchans, int *nchans, struct ieee80211_channel chans[])
+{
+ struct iwm_softc *sc = ic->ic_softc;
+ uint8_t bands[IEEE80211_MODE_BYTES];
+ size_t ch_num;
+
+ memset(bands, 0, sizeof(bands));
+ /* 1-13: 11b/g channels. */
+ setbit(bands, IEEE80211_MODE_11B);
+ setbit(bands, IEEE80211_MODE_11G);
+ iwm_add_channel_band(sc, chans, maxchans, nchans, 0,
+ IWM_NUM_2GHZ_CHANNELS - 1, bands);
+
+ /* 14: 11b channel only. */
+ clrbit(bands, IEEE80211_MODE_11G);
+ iwm_add_channel_band(sc, chans, maxchans, nchans,
+ IWM_NUM_2GHZ_CHANNELS - 1, IWM_NUM_2GHZ_CHANNELS, bands);
+
+ if (sc->sc_nvm.sku_cap_band_52GHz_enable) {
+ if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)
+ ch_num = nitems(iwm_nvm_channels);
+ else
+ ch_num = nitems(iwm_nvm_channels_8000);
+ memset(bands, 0, sizeof(bands));
+ setbit(bands, IEEE80211_MODE_11A);
+ iwm_add_channel_band(sc, chans, maxchans, nchans,
+ IWM_NUM_2GHZ_CHANNELS, ch_num, bands);
+ }
+}
+
#ifndef IEEE80211_NO_HT
static void
@@ -3250,12 +3279,14 @@
data->lar_enabled = !!(lar_config & IWM_NVM_LAR_ENABLED_8000);
}
- if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)
- iwm_init_channel_map(sc, &nvm_sw[IWM_NVM_CHANNELS],
- iwm_nvm_channels, __arraycount(iwm_nvm_channels));
- else
- iwm_init_channel_map(sc, ®ulatory[IWM_NVM_CHANNELS_8000],
- iwm_nvm_channels_8000, __arraycount(iwm_nvm_channels_8000));
+ if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
+ memcpy(data->nvm_ch_flags, sc->sc_nvm_sdp ?
+ ®ulatory[0] : &nvm_sw[IWM_NVM_CHANNELS],
+ __arraycount(iwm_nvm_channels) * sizeof(uint16_t));
+ } else {
+ memcpy(data->nvm_ch_flags, ®ulatory[IWM_NVM_CHANNELS_8000],
+ __arraycount(iwm_nvm_channels_8000) * sizeof(uint16_t));
+ }
data->calib_version = 255; /* TODO:
this value will prevent some checks from
@@ -3280,7 +3311,13 @@
}
hw = (const uint16_t *) sections[IWM_NVM_SECTION_TYPE_HW].data;
- } else if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) {
+ regulatory = (const uint16_t *)
+ sections[sc->sc_nvm_sdp ?
+ IWM_NVM_SECTION_TYPE_REGULATORY_SDP
+ : IWM_NVM_SECTION_TYPE_REGULATORY].data;
+ if (regulatory == NULL)
+ return ENOENT;
+ } else if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) {
/* SW and REGULATORY sections are mandatory */
if (!sections[IWM_NVM_SECTION_TYPE_SW].data ||
!sections[IWM_NVM_SECTION_TYPE_REGULATORY].data) {
@@ -6883,34 +6920,6 @@
return err;
}
-static void
-iwm_get_radiocaps(struct ieee80211com *ic,
- int maxchans, int *nchans, struct ieee80211_channel chans[])
-{
- uint8_t bands[IEEE80211_MODE_BYTES];
-
- /*
- * NNN Should be able to do something based on chip if
- * a chip has more bands .... eg. N ... but for the future.
- */
-
- memset(bands, 0, sizeof(bands));
- setbit(bands, IEEE80211_MODE_11A);
- setbit(bands, IEEE80211_MODE_11B);
- setbit(bands, IEEE80211_MODE_11G);
-#ifndef IEEE80211_NO_HT
- setbit(bands, IEEE80211_MODE_11NG);
- setbit(bands, IEEE80211_MODE_11NA);
-#endif
-#if 0 /* what about non-2ghz channels? but ieee80211_init_channels does not
- respect an allocation limit "maxchans" */
- /* XXX get regdomain from FW and pass instead of NULL */
- ieee80211_init_channels(ic, NULL, bands);
- *nchans = max(maxchans, ic->ic_nchans);
-#endif
- ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
-}
-
static int
iwm_init(struct iwm_softc *sc)
{
@@ -7943,6 +7952,7 @@
sc->apmg_wake_up_wa = 1;
sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
+ sc->sc_nvm_sdp = 1;
break;
case PCI_PRODUCT_INTEL_WIFI_LINK_7260_1:
case PCI_PRODUCT_INTEL_WIFI_LINK_7260_2:
@@ -8223,27 +8233,9 @@
iwm_preinit(sc);
sc->sc_flags |= IWM_FLAG_STOPPED;
- /* Set supported legacy rates. */
-#ifdef notused
- if (sc->sc_flags & IWM_FLAG_HAS_11N) {
- /* Set supported HT rates. */
- ic->ic_sup_mcs[0] = 0xff; /* MCS 0-7 */
- if (sc->nrxchains > 1)
- ic->ic_sup_mcs[1] = 0xff; /* MCS 7-15 */
- if (sc->nrxchains > 2)
- ic->ic_sup_mcs[2] = 0xff; /* MCS 16-23 */
- }
-#endif
-
-#if 0
- /* IBSS channel undefined for now. */
- ic->ic_curchan = &ic->ic_channels[0];
-#endif
-
iwm_get_radiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans,
ic->ic_channels);
- //ifp->if_percpuq = if_percpuq_create(ifp);
ieee80211_ifattach(ic);
ic->ic_vap_create = iwm_vap_create;
diff -r 400cc3f7b5c3 -r 2bd71240df78 sys/dev/pci/if_iwmreg.h
--- a/sys/dev/pci/if_iwmreg.h Mon Jan 18 11:45:37 2021 +0100
+++ b/sys/dev/pci/if_iwmreg.h Mon Jan 18 20:08:02 2021 +0100
@@ -2119,7 +2119,9 @@
IWM_NVM_SECTION_TYPE_CALIBRATION,
Home |
Main Index |
Thread Index |
Old Index