From 25594bd74315ef3e8d8f0a3c7317a5c985f2cbc7 Mon Sep 17 00:00:00 2001 From: stsp Date: Wed, 20 Jul 2016 10:26:42 +0000 Subject: [PATCH] Bring iwn_update_htprot() back, so iwn(4) will properly keep track of HT protection changes while associated. HT protection affects behaviour on Tx but is configured along with Rx settings (because Intel likes it that way). And our previous iwn_update_htprot() implementation had a bug where it would accidentally clear bits which enable CCK rates for Rx. The Intel Wireless-N 2200 chip accordingly stopped receiving some frames (most notably broadcast frames) and the link broke down. Also, restore the power-saving level after updating the Rx config (like Linux does), and add some DELAYs for good measure to ensure the firmware has time to process asynchronous commands we send. tested by myself and mlarkin@ ok mlarkin@ --- sys/dev/pci/if_iwn.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index 1c116dab39e..b67304de00b 100644 --- a/sys/dev/pci/if_iwn.c +++ b/sys/dev/pci/if_iwn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwn.c,v 1.167 2016/06/27 19:01:02 stsp Exp $ */ +/* $OpenBSD: if_iwn.c,v 1.168 2016/07/20 10:26:42 stsp Exp $ */ /*- * Copyright (c) 2007-2010 Damien Bergamini @@ -5046,11 +5046,8 @@ iwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, void iwn_update_htprot(struct ieee80211com *ic, struct ieee80211_node *ni) { - /* XXX Disabled for now. It seems to cause output errors - * (tx status=0x83) and to make block ack sessions degrade - * into a half-working state. */ -#if 0 struct iwn_softc *sc = ic->ic_softc; + struct iwn_ops *ops = &sc->ops; enum ieee80211_htprot htprot; struct iwn_rxon_assoc rxon_assoc; int s, error; @@ -5066,17 +5063,38 @@ iwn_update_htprot(struct ieee80211com *ic, struct ieee80211_node *ni) rxon_assoc.flags = sc->rxon.flags; rxon_assoc.filter = sc->rxon.filter; rxon_assoc.ofdm_mask = sc->rxon.ofdm_mask; + rxon_assoc.cck_mask = sc->rxon.cck_mask; rxon_assoc.ht_single_mask = sc->rxon.ht_single_mask; rxon_assoc.ht_dual_mask = sc->rxon.ht_dual_mask; rxon_assoc.ht_triple_mask = sc->rxon.ht_triple_mask; rxon_assoc.rxchain = sc->rxon.rxchain; rxon_assoc.acquisition = sc->rxon.acquisition; + s = splnet(); + error = iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &rxon_assoc, sizeof(rxon_assoc), 1); if (error != 0) printf("%s: RXON_ASSOC command failed\n", sc->sc_dev.dv_xname); -#endif + + DELAY(100); + + /* All RXONs wipe the firmware's txpower table. Restore it. */ + error = ops->set_txpower(sc, 1); + if (error != 0) + printf("%s: could not set TX power\n", sc->sc_dev.dv_xname); + + DELAY(100); + + /* Restore power saving level */ + if (ic->ic_flags & IEEE80211_F_PMGTON) + error = iwn_set_pslevel(sc, 0, 3, 1); + else + error = iwn_set_pslevel(sc, 0, 0, 1); + if (error != 0) + printf("%s: could not set PS level\n", sc->sc_dev.dv_xname); + + splx(s); } /* -- 2.20.1