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/1ee5489cf1a2
branches:  trunk
changeset: 1025466:1ee5489cf1a2
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 05ad46fd4c2a -r 1ee5489cf1a2 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, &regulatory[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 ?
+                   &regulatory[0] : &nvm_sw[IWM_NVM_CHANNELS],
+                   __arraycount(iwm_nvm_channels) * sizeof(uint16_t));
+       } else {
+               memcpy(data->nvm_ch_flags, &regulatory[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 05ad46fd4c2a -r 1ee5489cf1a2 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