summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2016-07-20 10:26:43 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2016-07-20 10:26:43 +0000
commit5cdde35b81298204f0550369ff00d84823ef57ec (patch)
tree6843af10b2d7fb4bced021f86cb9cdb55c8a940d /sys
parentc694f6b05682e6db4a1ff01aed7b1f50ed8bf7b6 (diff)
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@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_iwn.c30
1 files 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 <damien.bergamini@free.fr>
@@ -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);
}
/*