From: stsp Date: Sat, 11 Sep 2021 17:28:44 +0000 (+0000) Subject: Zero out iwx(4) Tx descriptors of frames which are done. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=5d86ffb30f419b5493b77ec776d3d191674ddbd2;p=openbsd Zero out iwx(4) Tx descriptors of frames which are done. This will hopefully prevent the device from ever writing to the former DMA address of a buffer which has been taken off the Tx ring. As far as I understand, the Linux driver unmaps (parts of) Tx descriptors that are done. We use a static DMA mapping for the entire descriptor array, so unmapping is not an option for us. Tested by several as part of my Tx aggregation support patch. --- diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index a71b7d0e614..5b58d964d12 100644 --- a/sys/dev/pci/if_iwx.c +++ b/sys/dev/pci/if_iwx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwx.c,v 1.108 2021/09/11 17:28:04 stsp Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.109 2021/09/11 17:28:44 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh @@ -4385,6 +4385,25 @@ iwx_rx_tx_cmd_single(struct iwx_softc *sc, struct iwx_rx_packet *pkt, if (txfail) ifp->if_oerrors++; } + +void +iwx_clear_tx_desc(struct iwx_softc *sc, struct iwx_tx_ring *ring, int idx) +{ + struct iwx_tfh_tfd *desc = &ring->desc[idx]; + uint8_t num_tbs = le16toh(desc->num_tbs) & 0x1f; + int i; + + /* First TB is never cleared - it is bidirectional DMA data. */ + for (i = 1; i < num_tbs; i++) { + struct iwx_tfh_tb *tb = &desc->tbs[i]; + memset(tb, 0, sizeof(*tb)); + } + desc->num_tbs = 0; + + bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, + (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr, + sizeof(*desc), BUS_DMASYNC_PREWRITE); +} void iwx_txd_done(struct iwx_softc *sc, struct iwx_tx_data *txd) @@ -4442,6 +4461,7 @@ iwx_rx_tx_cmd(struct iwx_softc *sc, struct iwx_rx_packet *pkt, txd = &ring->data[ring->tail]; if (txd->m != NULL) { iwx_txd_done(sc, txd); + iwx_clear_tx_desc(sc, ring, ring->tail); iwx_tx_update_byte_tbl(ring, ring->tail, 0, 0); ring->queued--; }