Fix 11g ifmedia modes in ath(4) (shown by 'ifconfig ath0 media').
authorstsp <stsp@openbsd.org>
Wed, 31 Jan 2018 11:27:03 +0000 (11:27 +0000)
committerstsp <stsp@openbsd.org>
Wed, 31 Jan 2018 11:27:03 +0000 (11:27 +0000)
There was code which set them up but didn't include 11b channels which
are part of 11g. And there was a hack which effectively stripped important
flag bits away and wouldn't work for modes with overlapping channels (b/g).
As a result, some flags were missing from 11g channels the driver reported
to net80211, which skipped over those channels when building the media list.

This gets us one step closer to supporting the AR5424.

ok mpi@

sys/dev/ic/ar5211.c
sys/dev/ic/ar5212.c
sys/dev/ic/ar5xxx.c
sys/dev/ic/ath.c

index 956256e..221f044 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar5211.c,v 1.49 2017/10/15 13:06:12 stsp Exp $        */
+/*     $OpenBSD: ar5211.c,v 1.50 2018/01/31 11:27:03 stsp Exp $        */
 
 /*
  * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
@@ -443,24 +443,25 @@ ar5k_ar5211_reset(struct ath_hal *hal, HAL_OPMODE op_mode, HAL_CHANNEL *channel,
         */
        hal->ah_op_mode = op_mode;
 
-       switch (channel->c_channel_flags & CHANNEL_MODES) {
-       case CHANNEL_A:
+       if ((channel->c_channel_flags & CHANNEL_A) == CHANNEL_A) {
                mode = AR5K_INI_VAL_11A;
                freq = AR5K_INI_RFGAIN_5GHZ;
                ee_mode = AR5K_EEPROM_MODE_11A;
-               break;
-       case CHANNEL_B:
-               mode = AR5K_INI_VAL_11B;
+       } else if ((channel->c_channel_flags & CHANNEL_B) == CHANNEL_B) {
+               if (hal->ah_capabilities.cap_mode & HAL_MODE_11B) {
+                       mode = AR5K_INI_VAL_11B;
+                       ee_mode = AR5K_EEPROM_MODE_11B;
+               } else {
+                       mode = AR5K_INI_VAL_11G;
+                       ee_mode = AR5K_EEPROM_MODE_11G;
+               }
                freq = AR5K_INI_RFGAIN_2GHZ;
-               ee_mode = AR5K_EEPROM_MODE_11B;
-               break;
-       case CHANNEL_G:
-       case CHANNEL_PUREG:
+       } else if ((channel->c_channel_flags & (CHANNEL_G | CHANNEL_PUREG)) ==
+           (CHANNEL_G | CHANNEL_PUREG)) {
                mode = AR5K_INI_VAL_11G;
                freq = AR5K_INI_RFGAIN_2GHZ;
                ee_mode = AR5K_EEPROM_MODE_11G;
-               break;
-       default:
+       } else {
                AR5K_PRINTF("invalid channel: %d\n", channel->c_channel);
                return (AH_FALSE);
        }
index 50a9b29..6ed3468 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar5212.c,v 1.57 2017/10/15 13:06:12 stsp Exp $        */
+/*     $OpenBSD: ar5212.c,v 1.58 2018/01/31 11:27:03 stsp Exp $        */
 
 /*
  * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
@@ -505,29 +505,30 @@ ar5k_ar5212_reset(struct ath_hal *hal, HAL_OPMODE op_mode, HAL_CHANNEL *channel,
         */
        hal->ah_op_mode = op_mode;
 
-       switch (channel->c_channel_flags & CHANNEL_MODES) {
-       case CHANNEL_A:
+       if ((channel->c_channel_flags & CHANNEL_A) == CHANNEL_A) {
                mode = AR5K_INI_VAL_11A;
                freq = AR5K_INI_RFGAIN_5GHZ;
                ee_mode = AR5K_EEPROM_MODE_11A;
-               break;
-       case CHANNEL_B:
-               mode = AR5K_INI_VAL_11B;
+       } else if ((channel->c_channel_flags & CHANNEL_B) == CHANNEL_B) {
+               if (hal->ah_capabilities.cap_mode & HAL_MODE_11B) {
+                       mode = AR5K_INI_VAL_11B;
+                       ee_mode = AR5K_EEPROM_MODE_11B;
+               } else {
+                       mode = AR5K_INI_VAL_11B;
+                       mode = AR5K_INI_VAL_11G;
+                       ee_mode = AR5K_EEPROM_MODE_11G;
+               }
                freq = AR5K_INI_RFGAIN_2GHZ;
-               ee_mode = AR5K_EEPROM_MODE_11B;
-               break;
-       case CHANNEL_G:
-       case CHANNEL_PUREG:
+       } else if ((channel->c_channel_flags & (CHANNEL_G | CHANNEL_PUREG)) ==
+           (CHANNEL_G | CHANNEL_PUREG)) {
                mode = AR5K_INI_VAL_11G;
                freq = AR5K_INI_RFGAIN_2GHZ;
                ee_mode = AR5K_EEPROM_MODE_11G;
-               break;
-       case CHANNEL_XR:
+       } else if ((channel->c_channel_flags & CHANNEL_XR) == CHANNEL_XR) {
                mode = AR5K_INI_VAL_XR;
                freq = AR5K_INI_RFGAIN_5GHZ;
                ee_mode = AR5K_EEPROM_MODE_11A;
-               break;
-       default:
+       } else {
                AR5K_PRINTF("invalid channel: %d\n", channel->c_channel);
                return (AH_FALSE);
        }
index a927143..416ab96 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar5xxx.c,v 1.62 2017/08/25 10:04:36 tb Exp $  */
+/*     $OpenBSD: ar5xxx.c,v 1.63 2018/01/31 11:27:03 stsp Exp $        */
 
 /*
  * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
@@ -472,11 +472,11 @@ ath_hal_init_channels(struct ath_hal *hal, HAL_CHANNEL *channels,
                    (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_CCK))
                        all_channels[c].c_channel_flags = CHANNEL_B;
 
-               if ((hal->ah_capabilities.cap_mode & HAL_MODE_11G) &&
-                   (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_OFDM)) {
-                       all_channels[c].c_channel_flags |=
-                           hal->ah_version == AR5K_AR5211 ?
-                           CHANNEL_PUREG : CHANNEL_G;
+               if (hal->ah_capabilities.cap_mode & HAL_MODE_11G) {
+                       if (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_CCK)
+                           all_channels[c].c_channel_flags = CHANNEL_B;
+                       if (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_OFDM)
+                               all_channels[c].c_channel_flags |= (CHANNEL_G | CHANNEL_PUREG);
                }
 
                /* Write channel and increment counter */
index 164d57e..c0c5f42 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: ath.c,v 1.115 2017/05/31 09:17:39 stsp Exp $  */
+/*      $OpenBSD: ath.c,v 1.116 2018/01/31 11:27:03 stsp Exp $  */
 /*     $NetBSD: ath.c,v 1.37 2004/08/18 21:59:39 dyoung Exp $  */
 
 /*-
@@ -88,7 +88,6 @@ int   ath_ioctl(struct ifnet *, u_long, caddr_t);
 void   ath_fatal_proc(void *, int);
 void   ath_rxorn_proc(void *, int);
 void   ath_bmiss_proc(void *, int);
-u_int   ath_chan2flags(struct ieee80211com *, struct ieee80211_channel *);
 int    ath_initkeytable(struct ath_softc *);
 void    ath_mcastfilter_accum(caddr_t, u_int32_t (*)[2]);
 void    ath_mcastfilter_compute(struct ath_softc *, u_int32_t (*)[2]);
@@ -601,26 +600,6 @@ ath_bmiss_proc(void *arg, int pending)
        }
 }
 
-u_int
-ath_chan2flags(struct ieee80211com *ic, struct ieee80211_channel *chan)
-{
-       enum ieee80211_phymode mode = ieee80211_chan2mode(ic, chan);
-
-       switch (mode) {
-       case IEEE80211_MODE_AUTO:
-               return 0;
-       case IEEE80211_MODE_11A:
-               return CHANNEL_A;
-       case IEEE80211_MODE_11B:
-               return CHANNEL_B;
-       case IEEE80211_MODE_11G:
-               return CHANNEL_G;
-       default:
-               panic("%s: unsupported mode %d", __func__, mode);
-               return 0;
-       }
-}
-
 int
 ath_init(struct ifnet *ifp)
 {
@@ -666,7 +645,7 @@ ath_init1(struct ath_softc *sc)
         * and then setup of the interrupt mask.
         */
        hchan.channel = ic->ic_ibss_chan->ic_freq;
-       hchan.channelFlags = ath_chan2flags(ic, ic->ic_ibss_chan);
+       hchan.channelFlags = ic->ic_ibss_chan->ic_flags;
        if (!ath_hal_reset(ah, ic->ic_opmode, &hchan, AH_TRUE, &status)) {
                printf("%s: unable to reset hardware; hal status %u\n",
                        ifp->if_xname, status);
@@ -789,12 +768,11 @@ ath_reset(struct ath_softc *sc, int full)
        HAL_CHANNEL hchan;
 
        /*
-        * Convert to a HAL channel description with the flags
-        * constrained to reflect the current operating mode.
+        * Convert to a HAL channel description.
         */
        c = ic->ic_ibss_chan;
        hchan.channel = c->ic_freq;
-       hchan.channelFlags = ath_chan2flags(ic, c);
+       hchan.channelFlags = c->ic_flags;
 
        ath_hal_set_intr(ah, 0);                /* disable interrupts */
        ath_draintxq(sc);               /* stop xmit side */
@@ -2658,12 +2636,10 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
                ath_draintxq(sc);               /* clear pending tx frames */
                ath_stoprecv(sc);               /* turn off frame recv */
                /*
-                * Convert to a HAL channel description with
-                * the flags constrained to reflect the current
-                * operating mode.
+                * Convert to a HAL channel description.
                 */
                hchan.channel = chan->ic_freq;
-               hchan.channelFlags = ath_chan2flags(ic, chan);
+               hchan.channelFlags = chan->ic_flags;
                if (!ath_hal_reset(ah, ic->ic_opmode, &hchan, AH_TRUE,
                    &status)) {
                        printf("%s: ath_chan_set: unable to reset "
@@ -2753,12 +2729,11 @@ ath_calibrate(void *arg)
        sc->sc_stats.ast_per_cal++;
 
        /*
-        * Convert to a HAL channel description with the flags
-        * constrained to reflect the current operating mode.
+        * Convert to a HAL channel description.
         */
        c = ic->ic_ibss_chan;
        hchan.channel = c->ic_freq;
-       hchan.channelFlags = ath_chan2flags(ic, c);
+       hchan.channelFlags = c->ic_flags;
 
        s = splnet();
        DPRINTF(ATH_DEBUG_CALIBRATE,