diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2019-05-09 16:13:35 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2019-05-09 16:13:35 +0000 |
commit | 38d9bc99f56bc8019d4320aa7dac59f91ec39b2d (patch) | |
tree | f905289eabd6d825829801f5bbb07ced75ff8f59 /sys/dev | |
parent | eb07130aa6d1ae6d06666fd1023fe78ed674ecde (diff) |
Add two sanity checks to iwm's firmware notification interrupt handler:
1) Clamp firmware-provided index into the rx ring to the size of the ring.
Linux started doing this, too, to work around HW bugs in the 9000 series.
(mathes Linux 5eae443eb5e2b3777582ea37c6a002171ec134d5)
2) Don't call iwm_cmd_done() if the firmware response in the Rx buffer
is not recognized. We should just skip such buffers, not act on them.
ok beck kevlo mpi
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_iwm.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c index 335033d2109..981936fd3a5 100644 --- a/sys/dev/pci/if_iwm.c +++ b/sys/dev/pci/if_iwm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwm.c,v 1.239 2019/04/01 10:47:13 kn Exp $ */ +/* $OpenBSD: if_iwm.c,v 1.240 2019/05/09 16:13:34 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> @@ -7000,10 +7000,11 @@ iwm_notif_intr(struct iwm_softc *sc) 0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD); hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff; + hw &= (IWM_RX_RING_COUNT - 1); while (sc->rxq.cur != hw) { struct iwm_rx_data *data = &sc->rxq.data[sc->rxq.cur]; struct iwm_rx_packet *pkt; - int qid, idx, code; + int qid, idx, code, handled = 1; bus_dmamap_sync(sc->sc_dmat, data->map, 0, sizeof(*pkt), BUS_DMASYNC_POSTREAD); @@ -7256,6 +7257,7 @@ iwm_notif_intr(struct iwm_softc *sc) } default: + handled = 0; printf("%s: unhandled firmware response 0x%x/0x%x " "rx ring %d[%d]\n", DEVNAME(sc), pkt->hdr.code, pkt->len_n_flags, qid, @@ -7270,7 +7272,7 @@ iwm_notif_intr(struct iwm_softc *sc) * For example, uCode issues IWM_REPLY_RX when it sends a * received frame to the driver. */ - if (!(pkt->hdr.qid & (1 << 7))) { + if (handled && !(pkt->hdr.qid & (1 << 7))) { iwm_cmd_done(sc, pkt); } |