From: stsp Date: Wed, 20 Jul 2016 10:26:42 +0000 (+0000) Subject: Bring iwn_update_htprot() back, so iwn(4) will properly keep track X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=25594bd74315ef3e8d8f0a3c7317a5c985f2cbc7;p=openbsd 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@ --- 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); } /*