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 Only map channels from epprom - from FreeBSD.



details:   https://anonhg.NetBSD.org/src-all/rev/7ce53837fbd8
branches:  trunk
changeset: 376435:7ce53837fbd8
user:      Nathanial Sloss <nat%netbsd.org@localhost>
date:      Sun Jun 18 15:05:48 2023 +1000

description:
Only map channels from epprom - from FreeBSD.

diffstat:

 sys/dev/pci/if_iwn.c    |  167 +++++++++++++++++++++++++++++++++++++++++------
 sys/dev/pci/if_iwnvar.h |    1 +
 2 files changed, 147 insertions(+), 21 deletions(-)

diffs (206 lines):

diff -r 8a30b93978eb -r 7ce53837fbd8 sys/dev/pci/if_iwn.c
--- a/sys/dev/pci/if_iwn.c      Fri Apr 28 22:38:34 2023 +1000
+++ b/sys/dev/pci/if_iwn.c      Sun Jun 18 15:05:48 2023 +1000
@@ -268,6 +268,11 @@ static int iwn_raw_xmit(struct ieee80211
 static void    iwn4965_print_power_group(struct iwn_softc *, int);
 #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, 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 void    iwn_read_eeprom_enhinfo(struct iwn_softc *);
 static void    iwn_newassoc(struct ieee80211_node *, int);
@@ -463,26 +468,13 @@ iwn_get_radiocaps(struct ieee80211com *i
     int maxchans, int *nchans, struct ieee80211_channel chans[])
 {
        struct iwn_softc *sc = ic->ic_softc;
-        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));
-       if (sc->sc_flags & IWN_FLAG_HAS_5GHZ)
-               setbit(bands, IEEE80211_MODE_11A);
-        setbit(bands, IEEE80211_MODE_11B);
-        setbit(bands, IEEE80211_MODE_11G);
-#ifndef IEEE80211_NO_HT
-       setbit(bands, IEEE80211_MODE_11NG);
-       if (sc->sc_flags & IWN_FLAG_HAS_5GHZ)
-               setbit(bands, IEEE80211_MODE_11NA);
-#endif
-       /* XXX is it still safe to use NULL here as ic channels are populated
-          when firmware is read */
-        ieee80211_init_channels(ic, NULL, bands);
+       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);
 }
 
 static void
@@ -2074,12 +2066,145 @@ iwn5000_read_eeprom(struct iwn_softc *sc
        }
 }
 
+/*
+ * Translate EEPROM flags to net80211.
+ */
+static uint32_t
+iwn_eeprom_channel_flags(struct iwn_eeprom_chan *channel)
+{
+       uint32_t nflags;
+
+       nflags = 0;
+       if ((channel->flags & IWN_EEPROM_CHAN_ACTIVE) == 0)
+               nflags |= IEEE80211_CHAN_PASSIVE;
+       if ((channel->flags & IWN_EEPROM_CHAN_IBSS) == 0)
+               nflags |= IEEE80211_CHAN_NOADHOC;
+       if (channel->flags & IWN_EEPROM_CHAN_RADAR) {
+               nflags |= IEEE80211_CHAN_DFS;
+               /* XXX apparently IBSS may still be marked */
+               nflags |= IEEE80211_CHAN_NOADHOC;
+       }
+
+       return nflags;
+}
+
+static void
+iwn_read_eeprom_band(struct iwn_softc *sc, int n, int maxchans, int *nchans,
+    struct ieee80211_channel chans[])
+{
+       struct iwn_eeprom_chan *channels = &sc->eeprom_channels[n];
+       const struct iwn_chan_band *band = &iwn_bands[n];
+       uint8_t bands[IEEE80211_MODE_BYTES];
+       uint8_t chan;
+       int i, error, nflags;
+
+       DPRINTF((sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__));
+
+       memset(bands, 0, sizeof(bands));
+       if (n == 0) {
+               setbit(bands, IEEE80211_MODE_11B);
+               setbit(bands, IEEE80211_MODE_11G);
+               if (sc->sc_flags & IWN_FLAG_HAS_11N)
+                       setbit(bands, IEEE80211_MODE_11NG);
+       } else {
+               setbit(bands, IEEE80211_MODE_11A);
+               if (sc->sc_flags & IWN_FLAG_HAS_11N)
+                       setbit(bands, IEEE80211_MODE_11NA);
+       }
+
+       for (i = 0; i < band->nchan; i++) {
+               if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID)) {
+                       DPRINTF((sc, IWN_DEBUG_RESET,
+                           "skip chan %d flags 0x%x maxpwr %d\n",
+                           band->chan[i], channels[i].flags,
+                           channels[i].maxpwr));
+                       continue;
+               }
+
+               chan = band->chan[i];
+               nflags = iwn_eeprom_channel_flags(&channels[i]);
+               error = ieee80211_add_channel(chans, maxchans, nchans,
+                   chan, 0, channels[i].maxpwr, nflags, bands);
+               if (error != 0)
+                       break;
+
+               /* Save maximum allowed TX power for this channel. */
+               /* XXX wrong */
+               sc->maxpwr[chan] = channels[i].maxpwr;
+
+               DPRINTF((sc, IWN_DEBUG_RESET,
+                   "add chan %d flags 0x%x maxpwr %d\n", chan,
+                   channels[i].flags, channels[i].maxpwr));
+       }
+
+       DPRINTF((sc, IWN_DEBUG_TRACE, "->%s end\n", __func__));
+
+}
+
+void
+iwn_read_eeprom_ht40(struct iwn_softc *sc, int n, int maxchans, int *nchans,
+    struct ieee80211_channel chans[])
+{
+       struct iwn_eeprom_chan *channels = &sc->eeprom_channels[n];
+       const struct iwn_chan_band *band = &iwn_bands[n];
+       uint8_t chan;
+       int i, error, nflags;
+
+       DPRINTF((sc, IWN_DEBUG_TRACE, "->%s start\n", __func__));
+
+       if (!(sc->sc_flags & IWN_FLAG_HAS_11N)) {
+               DPRINTF((sc, IWN_DEBUG_TRACE, "->%s end no 11n\n", __func__));
+               return;
+       }
+
+       for (i = 0; i < band->nchan; i++) {
+               if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID)) {
+                       DPRINTF((sc, IWN_DEBUG_RESET,
+                           "skip chan %d flags 0x%x maxpwr %d\n",
+                           band->chan[i], channels[i].flags,
+                           channels[i].maxpwr));
+                       continue;
+               }
+
+               chan = band->chan[i];
+               nflags = iwn_eeprom_channel_flags(&channels[i]);
+               nflags |= (n == 5 ? IEEE80211_CHAN_G : IEEE80211_CHAN_A);
+               error = ieee80211_add_channel_ht40(chans, maxchans, nchans,
+                   chan, channels[i].maxpwr, nflags);
+               switch (error) {
+               case EINVAL:
+                       device_printf(sc->sc_dev,
+                           "%s: no entry for channel %d\n", __func__, chan);
+                       continue;
+               case ENOENT:
+                       DPRINTF((sc, IWN_DEBUG_RESET,
+                           "%s: skip chan %d, extension channel not found\n",
+                           __func__, chan));
+                       continue;
+               case ENOBUFS:
+                       device_printf(sc->sc_dev,
+                           "%s: channel table is full!\n", __func__);
+                       break;
+               case 0:
+                       DPRINTF((sc, IWN_DEBUG_RESET,
+                           "add ht40 chan %d flags 0x%x maxpwr %d\n",
+                           chan, channels[i].flags, channels[i].maxpwr));
+                       /* FALLTHROUGH */
+               default:
+                       break;
+               }
+       }
+
+       DPRINTF((sc, IWN_DEBUG_TRACE, "->%s end\n", __func__));
+
+}
+
 static void
 iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr)
 {
        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 iwn_eeprom_chan channels[IWN_MAX_CHAN_PER_BAND];
        uint8_t chan;
        int i;
 
diff -r 8a30b93978eb -r 7ce53837fbd8 sys/dev/pci/if_iwnvar.h
--- a/sys/dev/pci/if_iwnvar.h   Fri Apr 28 22:38:34 2023 +1000
+++ b/sys/dev/pci/if_iwnvar.h   Sun Jun 18 15:05:48 2023 +1000
@@ -342,5 +342,6 @@ struct iwn_softc {
        kcondvar_t              t_event;        
 
        int                     sc_beacon_wait; /* defer/skip sending */
+       struct iwn_eeprom_chan  eeprom_channels[IWN_MAX_CHAN_PER_BAND];
 };
 



Home | Main Index | Thread Index | Old Index