summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2020-04-13 18:41:31 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2020-04-13 18:41:31 +0000
commit384cbe3b1bc3d6b900b7a8aebcd81c60cf3b06cc (patch)
treeb2a5cd5f7ddd3d4a7b8ef30f3e8fec5114f64156 /sys
parent6af0448783bd9a0505e6c6248be39e08292148cd (diff)
Fix a recently introduced iwn(4) problem where the link gets stuck since
every CCMP encrypted frame is discarded by the AP as a replay. This happened because of CCMP frames with out of range PNs sent by hardware. It seems iwn firmware doesn't like it if we reset the Tx scheduler slot for a frame which is still within the firmware's block ack window, even if the frame has already been ACKed. So frames now get cleared off the Tx queue only when the block ack window has moved past them, which is good enough and seems to prevent the problem. Problem reproduced and fix tested by both myself and jca@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_iwn.c14
1 files changed, 5 insertions, 9 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c
index 1751328768d..2a1f1c26191 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.222 2020/04/09 07:20:08 stsp Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.223 2020/04/13 18:41:30 stsp Exp $ */
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -2259,7 +2259,6 @@ void
iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
struct iwn_rx_data *data)
{
- struct iwn_ops *ops = &sc->ops;
struct iwn_compressed_ba *cba = (struct iwn_compressed_ba *)(desc + 1);
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
@@ -2322,9 +2321,9 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn);
while (nsent && idx != end_idx) {
struct iwn_tx_data *txdata = &txq->data[idx];
- int have_ack = (le64toh(cba->bitmap) & (1 << bit++));
+ int have_ack = (le64toh(cba->bitmap) & (1 << bit));
- if (txdata->m != NULL) {
+ if ((ba->ba_bitmap & (1 << bit)) == 0) {
/*
* Don't report frames to MiRA which were sent
* at a different Tx rate than ni->ni_txmcs.
@@ -2339,18 +2338,15 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
if (!have_ack || txdata->txfail > 0)
wn->mn.txfail++;
}
- if (have_ack) {
+ if (have_ack)
ieee80211_output_ba_record_ack(ic,
ni, cba->tid, ssn);
- ops->reset_sched(sc, qid, idx);
- iwn_tx_done_free_txdata(sc, txdata);
- txq->queued--;
- }
}
idx = (idx + 1) % IWN_TX_RING_COUNT;
ssn = (ssn + 1) % 0xfff;
nsent--;
+ bit++;
}
if (wn->mn.ampdu_size > 0)