diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2020-04-29 13:13:31 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2020-04-29 13:13:31 +0000 |
commit | 31659b312511a17a823e8dafac808d0c793ced0e (patch) | |
tree | 265d8cde26a76b26a3b192aa72700e37f46f3ebf /sys | |
parent | b0780212916419166a6fdd8caec2457cbd712e99 (diff) |
Add the 'nomimo' nwflag which disables MIMO in 11n mode.
This flag restricts a wireless driver to MCS0 - MCS7 for both transmission
and reception. It can be set to work around packet loss in 11n mode caused
by unused antenna connectors on a MIMO-capable wireless network device.
man page tweak from tracey@
ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/athn.c | 89 | ||||
-rw-r--r-- | sys/dev/pci/if_iwm.c | 24 | ||||
-rw-r--r-- | sys/dev/pci/if_iwx.c | 22 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ioctl.h | 8 |
4 files changed, 93 insertions, 50 deletions
diff --git a/sys/dev/ic/athn.c b/sys/dev/ic/athn.c index 0683a8802b2..40725b02c43 100644 --- a/sys/dev/ic/athn.c +++ b/sys/dev/ic/athn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: athn.c,v 1.106 2020/04/28 06:58:09 stsp Exp $ */ +/* $OpenBSD: athn.c,v 1.107 2020/04/29 13:13:29 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> @@ -180,6 +180,53 @@ struct cfdriver athn_cd = { NULL, "athn", DV_IFNET }; +void +athn_config_ht(struct athn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + int i, ntxstreams, nrxstreams; + + if ((sc->flags & ATHN_FLAG_11N) == 0) + return; + + /* Set HT capabilities. */ + ic->ic_htcaps = (IEEE80211_HTCAP_SMPS_DIS << + IEEE80211_HTCAP_SMPS_SHIFT); +#ifdef notyet + ic->ic_htcaps |= IEEE80211_HTCAP_CBW20_40 | + IEEE80211_HTCAP_SGI40 | + IEEE80211_HTCAP_DSSSCCK40; +#endif + ic->ic_htxcaps = 0; +#ifdef notyet + if (AR_SREV_9271(sc) || AR_SREV_9287_10_OR_LATER(sc)) + ic->ic_htcaps |= IEEE80211_HTCAP_SGI20; + if (AR_SREV_9380_10_OR_LATER(sc)) + ic->ic_htcaps |= IEEE80211_HTCAP_LDPC; + if (AR_SREV_9280_10_OR_LATER(sc)) { + ic->ic_htcaps |= IEEE80211_HTCAP_TXSTBC; + ic->ic_htcaps |= 1 << IEEE80211_HTCAP_RXSTBC_SHIFT; + } +#endif + ntxstreams = sc->ntxchains; + nrxstreams = sc->nrxchains; + if (!AR_SREV_9380_10_OR_LATER(sc)) { + ntxstreams = MIN(ntxstreams, 2); + nrxstreams = MIN(nrxstreams, 2); + } + /* Set supported HT rates. */ + if (ic->ic_userflags & IEEE80211_F_NOMIMO) + ntxstreams = nrxstreams = 1; + memset(ic->ic_sup_mcs, 0, sizeof(ic->ic_sup_mcs)); + for (i = 0; i < nrxstreams; i++) + ic->ic_sup_mcs[i] = 0xff; + ic->ic_tx_mcs_set = IEEE80211_TX_MCS_SET_DEFINED; + if (ntxstreams != nrxstreams) { + ic->ic_tx_mcs_set |= IEEE80211_TX_RX_MCS_NOT_EQUAL; + ic->ic_tx_mcs_set |= (ntxstreams - 1) << 2; + } +} + int athn_attach(struct athn_softc *sc) { @@ -302,43 +349,7 @@ athn_attach(struct athn_softc *sc) IEEE80211_C_SHPREAMBLE | /* Short preamble supported. */ IEEE80211_C_PMGT; /* Power saving supported. */ - if (sc->flags & ATHN_FLAG_11N) { - int i, ntxstreams, nrxstreams; - - /* Set HT capabilities. */ - ic->ic_htcaps = (IEEE80211_HTCAP_SMPS_DIS << - IEEE80211_HTCAP_SMPS_SHIFT); -#ifdef notyet - ic->ic_htcaps |= IEEE80211_HTCAP_CBW20_40 | - IEEE80211_HTCAP_SGI40 | - IEEE80211_HTCAP_DSSSCCK40; -#endif - ic->ic_htxcaps = 0; -#ifdef notyet - if (AR_SREV_9271(sc) || AR_SREV_9287_10_OR_LATER(sc)) - ic->ic_htcaps |= IEEE80211_HTCAP_SGI20; - if (AR_SREV_9380_10_OR_LATER(sc)) - ic->ic_htcaps |= IEEE80211_HTCAP_LDPC; - if (AR_SREV_9280_10_OR_LATER(sc)) { - ic->ic_htcaps |= IEEE80211_HTCAP_TXSTBC; - ic->ic_htcaps |= 1 << IEEE80211_HTCAP_RXSTBC_SHIFT; - } -#endif - ntxstreams = sc->ntxchains; - nrxstreams = sc->nrxchains; - if (!AR_SREV_9380_10_OR_LATER(sc)) { - ntxstreams = MIN(ntxstreams, 2); - nrxstreams = MIN(nrxstreams, 2); - } - /* Set supported HT rates. */ - for (i = 0; i < nrxstreams; i++) - ic->ic_sup_mcs[i] = 0xff; - ic->ic_tx_mcs_set |= IEEE80211_TX_MCS_SET_DEFINED; - if (ntxstreams != nrxstreams) { - ic->ic_tx_mcs_set |= IEEE80211_TX_RX_MCS_NOT_EQUAL; - ic->ic_tx_mcs_set |= (ntxstreams - 1) << 2; - } - } + athn_config_ht(sc); /* Set supported rates. */ if (sc->flags & ATHN_FLAG_11G) { @@ -3070,6 +3081,8 @@ athn_init(struct ifnet *ifp) goto fail; } + athn_config_ht(sc); + /* Enable Rx. */ athn_rx_start(sc); diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c index 01c059a512b..906e910b02a 100644 --- a/sys/dev/pci/if_iwm.c +++ b/sys/dev/pci/if_iwm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwm.c,v 1.307 2020/04/09 21:36:50 stsp Exp $ */ +/* $OpenBSD: if_iwm.c,v 1.308 2020/04/29 13:13:30 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> @@ -324,6 +324,7 @@ int iwm_nvm_read_section(struct iwm_softc *, uint16_t, uint8_t *, uint16_t *, size_t); void iwm_init_channel_map(struct iwm_softc *, const uint16_t * const, const uint8_t *nvm_channels, int nchan); +int iwm_mimo_enabled(struct iwm_softc *); void iwm_setup_ht_rates(struct iwm_softc *); void iwm_htprot_task(void *); void iwm_update_htprot(struct ieee80211com *, struct ieee80211_node *); @@ -2861,6 +2862,15 @@ iwm_init_channel_map(struct iwm_softc *sc, const uint16_t * const nvm_ch_flags, } } +int +iwm_mimo_enabled(struct iwm_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + + return !sc->sc_nvm.sku_cap_mimo_disable && + (ic->ic_userflags & IEEE80211_F_NOMIMO) == 0; +} + void iwm_setup_ht_rates(struct iwm_softc *sc) { @@ -2870,9 +2880,10 @@ iwm_setup_ht_rates(struct iwm_softc *sc) /* TX is supported with the same MCS as RX. */ ic->ic_tx_mcs_set = IEEE80211_TX_MCS_SET_DEFINED; + memset(ic->ic_sup_mcs, 0, sizeof(ic->ic_sup_mcs)); ic->ic_sup_mcs[0] = 0xff; /* MCS 0-7 */ - if (sc->sc_nvm.sku_cap_mimo_disable) + if (!iwm_mimo_enabled(sc)) return; rx_ant = iwm_fw_valid_rx_ant(sc); @@ -5245,7 +5256,7 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node *in, int update) |= htole32(IWM_STA_FLG_MAX_AGG_SIZE_MSK | IWM_STA_FLG_AGG_MPDU_DENS_MSK); - if (!sc->sc_nvm.sku_cap_mimo_disable) { + if (iwm_mimo_enabled(sc)) { if (in->in_ni.ni_rxmcs[1] != 0) { add_sta_cmd.station_flags |= htole32(IWM_STA_FLG_MIMO_EN_MIMO2); @@ -6629,7 +6640,7 @@ iwm_run(struct iwm_softc *sc) /* Configure Rx chains for MIMO. */ if ((ic->ic_opmode == IEEE80211_M_MONITOR || (in->in_ni.ni_flags & IEEE80211_NODE_HT)) && - !sc->sc_nvm.sku_cap_mimo_disable) { + iwm_mimo_enabled(sc)) { err = iwm_phy_ctxt_cmd(sc, &sc->sc_phyctxt[0], 2, 2, IWM_FW_CTXT_ACTION_MODIFY, 0); if (err) { @@ -6755,7 +6766,7 @@ iwm_run_stop(struct iwm_softc *sc) /* Reset Tx chains in case MIMO was enabled. */ if ((in->in_ni.ni_flags & IEEE80211_NODE_HT) && - !sc->sc_nvm.sku_cap_mimo_disable) { + iwm_mimo_enabled(sc)) { err = iwm_phy_ctxt_cmd(sc, &sc->sc_phyctxt[0], 1, 1, IWM_FW_CTXT_ACTION_MODIFY, 0); if (err) { @@ -7727,6 +7738,9 @@ iwm_init(struct ifnet *ifp) return err; } + if (sc->sc_nvm.sku_cap_11n_enable) + iwm_setup_ht_rates(sc); + ifq_clr_oactive(&ifp->if_snd); ifp->if_flags |= IFF_RUNNING; diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index 27973d75877..64c3641a2d0 100644 --- a/sys/dev/pci/if_iwx.c +++ b/sys/dev/pci/if_iwx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwx.c,v 1.10 2020/04/03 08:32:21 stsp Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.11 2020/04/29 13:13:30 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> @@ -294,6 +294,7 @@ int iwx_nvm_read_section(struct iwx_softc *, uint16_t, uint8_t *, void iwx_init_channel_map(struct iwx_softc *, const uint16_t * const, const uint8_t *nvm_channels, int nchan); void iwx_setup_ht_rates(struct iwx_softc *); +int iwx_mimo_enabled(struct iwx_softc *); void iwx_htprot_task(void *); void iwx_update_htprot(struct ieee80211com *, struct ieee80211_node *); int iwx_ampdu_rx_start(struct ieee80211com *, struct ieee80211_node *, @@ -2709,6 +2710,15 @@ iwx_init_channel_map(struct iwx_softc *sc, const uint16_t * const nvm_ch_flags, } } +int +iwx_mimo_enabled(struct iwx_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + + return !sc->sc_nvm.sku_cap_mimo_disable && + (ic->ic_userflags & IEEE80211_F_NOMIMO) == 0; +} + void iwx_setup_ht_rates(struct iwx_softc *sc) { @@ -2718,9 +2728,10 @@ iwx_setup_ht_rates(struct iwx_softc *sc) /* TX is supported with the same MCS as RX. */ ic->ic_tx_mcs_set = IEEE80211_TX_MCS_SET_DEFINED; + memset(ic->ic_sup_mcs, 0, sizeof(ic->ic_sup_mcs)); ic->ic_sup_mcs[0] = 0xff; /* MCS 0-7 */ - if (sc->sc_nvm.sku_cap_mimo_disable) + if (!iwx_mimo_enabled(sc)) return; rx_ant = iwx_fw_valid_rx_ant(sc); @@ -5751,7 +5762,7 @@ iwx_run(struct iwx_softc *sc) /* Configure Rx chains for MIMO. */ if ((ic->ic_opmode == IEEE80211_M_MONITOR || (in->in_ni.ni_flags & IEEE80211_NODE_HT)) && - !sc->sc_nvm.sku_cap_mimo_disable) { + iwx_mimo_enabled(sc)) { err = iwx_phy_ctxt_cmd(sc, &sc->sc_phyctxt[0], 2, 2, IWX_FW_CTXT_ACTION_MODIFY, 0); if (err) { @@ -5872,7 +5883,7 @@ iwx_run_stop(struct iwx_softc *sc) /* Reset Tx chains in case MIMO was enabled. */ if ((in->in_ni.ni_flags & IEEE80211_NODE_HT) && - !sc->sc_nvm.sku_cap_mimo_disable) { + iwx_mimo_enabled(sc)) { err = iwx_phy_ctxt_cmd(sc, &sc->sc_phyctxt[0], 1, 1, IWX_FW_CTXT_ACTION_MODIFY, 0); if (err) { @@ -6430,6 +6441,9 @@ iwx_init(struct ifnet *ifp) return err; } + if (sc->sc_nvm.sku_cap_11n_enable) + iwx_setup_ht_rates(sc); + ifq_clr_oactive(&ifp->if_snd); ifp->if_flags |= IFF_RUNNING; diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index 94931282fe5..98c08a621b1 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_ioctl.h,v 1.39 2019/09/02 12:54:21 stsp Exp $ */ +/* $OpenBSD: ieee80211_ioctl.h,v 1.40 2020/04/29 13:13:30 stsp Exp $ */ /* $NetBSD: ieee80211_ioctl.h,v 1.7 2004/04/30 22:51:04 dyoung Exp $ */ /*- @@ -412,7 +412,8 @@ struct ieee80211_nodereq_all { #define IEEE80211_F_NOBRIDGE 0x00000002 /* CONF: no internal bridging */ #define IEEE80211_F_HOSTAPMASK 0x00000003 #define IEEE80211_F_STAYAUTH 0x00000004 /* CONF: ignore deauth */ -#define IEEE80211_F_USERBITS "\20\01HIDENWID\02NOBRIDGE\03STAYAUTH" +#define IEEE80211_F_NOMIMO 0x00000008 /* CONF: disable MIMO */ +#define IEEE80211_F_USERBITS "\20\01HIDENWID\02NOBRIDGE\03STAYAUTH\04NOMIMO" struct ieee80211_flags { const char *f_name; @@ -422,7 +423,8 @@ struct ieee80211_flags { #define IEEE80211_FLAGS { \ { "hidenwid", IEEE80211_F_HIDENWID }, \ { "nobridge", IEEE80211_F_NOBRIDGE }, \ - { "stayauth", IEEE80211_F_STAYAUTH } \ + { "stayauth", IEEE80211_F_STAYAUTH }, \ + { "nomimo", IEEE80211_F_NOMIMO } \ } #define SIOCG80211FLAGS _IOWR('i', 216, struct ifreq) |