diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2020-04-13 18:41:31 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2020-04-13 18:41:31 +0000 |
commit | 384cbe3b1bc3d6b900b7a8aebcd81c60cf3b06cc (patch) | |
tree | b2a5cd5f7ddd3d4a7b8ef30f3e8fec5114f64156 /sys/dev | |
parent | 6af0448783bd9a0505e6c6248be39e08292148cd (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/dev')
-rw-r--r-- | sys/dev/pci/if_iwn.c | 14 |
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) |