summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2020-04-29 13:13:31 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2020-04-29 13:13:31 +0000
commit31659b312511a17a823e8dafac808d0c793ced0e (patch)
tree265d8cde26a76b26a3b192aa72700e37f46f3ebf /sys
parentb0780212916419166a6fdd8caec2457cbd712e99 (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.c89
-rw-r--r--sys/dev/pci/if_iwm.c24
-rw-r--r--sys/dev/pci/if_iwx.c22
-rw-r--r--sys/net80211/ieee80211_ioctl.h8
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)