diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2015-11-24 10:04:35 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2015-11-24 10:04:35 +0000 |
commit | 1bef198472170a833f6871b702da2f4d423cc611 (patch) | |
tree | f13120bf3c616ae77b20966de9fbbb0157ba397d /sys/dev/pci/if_myx.c | |
parent | 59e72ac7b0a0a18ba6d12fc0eb00882b5073b2c4 (diff) |
fix tx ring accounting in myx_start.
turns out i was calculating the number of packets (not descriptors)
on the tx ring, and then using that as the free space for descriptors.
Diffstat (limited to 'sys/dev/pci/if_myx.c')
-rw-r--r-- | sys/dev/pci/if_myx.c | 44 |
1 files changed, 24 insertions, 20 deletions
diff --git a/sys/dev/pci/if_myx.c b/sys/dev/pci/if_myx.c index 0dbce5276b5..0c1b7d11740 100644 --- a/sys/dev/pci/if_myx.c +++ b/sys/dev/pci/if_myx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_myx.c,v 1.86 2015/11/19 12:46:08 dlg Exp $ */ +/* $OpenBSD: if_myx.c,v 1.87 2015/11/24 10:04:34 dlg Exp $ */ /* * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org> @@ -146,7 +146,8 @@ struct myx_softc { u_int32_t sc_tx_ring_offset; u_int sc_tx_nsegs; u_int32_t sc_tx_count; /* shadows ms_txdonecnt */ - u_int sc_tx_ring_idx; + u_int sc_tx_ring_prod; + u_int sc_tx_ring_cons; u_int sc_tx_prod; u_int sc_tx_cons; @@ -1032,7 +1033,8 @@ myx_up(struct myx_softc *sc) printf("%s: unable to get tx ring size\n", DEVNAME(sc)); goto free_pad; } - sc->sc_tx_ring_idx = 0; + sc->sc_tx_ring_prod = 0; + sc->sc_tx_ring_cons = 0; sc->sc_tx_ring_count = r / sizeof(struct myx_tx_desc); sc->sc_tx_nsegs = min(16, sc->sc_tx_ring_count / 4); /* magic */ sc->sc_tx_count = 0; @@ -1439,17 +1441,15 @@ myx_start(struct ifnet *ifp) IFQ_IS_EMPTY(&ifp->if_snd)) return; - prod = sc->sc_tx_prod; - cons = sc->sc_tx_cons; + idx = sc->sc_tx_ring_prod; /* figure out space */ - free = prod; - if (cons >= prod) + free = sc->sc_tx_ring_cons; + if (free <= idx) free += sc->sc_tx_ring_count; - free -= cons; + free -= idx; - /* keep track of our usage */ - cons = prod; + cons = prod = sc->sc_tx_prod; used = 0; @@ -1478,7 +1478,7 @@ myx_start(struct ifnet *ifp) map = ms->ms_map; bus_dmamap_sync(sc->sc_dmat, map, 0, - map->dm_mapsize, BUS_DMASYNC_POSTWRITE); + map->dm_mapsize, BUS_DMASYNC_PREWRITE); used += map->dm_nsegs + (map->dm_mapsize < 60 ? 1 : 0); @@ -1490,7 +1490,6 @@ myx_start(struct ifnet *ifp) return; ms = &sc->sc_tx_slots[cons]; - idx = sc->sc_tx_ring_idx; for (;;) { idx += ms->ms_map->dm_nsegs + @@ -1537,26 +1536,27 @@ myx_start(struct ifnet *ifp) txd.tx_flags = flags | MYXTXD_FLAGS_FIRST; /* make sure the first descriptor is seen after the others */ - myx_write_txd_tail(sc, ms, flags, offset, sc->sc_tx_ring_idx); + myx_write_txd_tail(sc, ms, flags, offset, sc->sc_tx_ring_prod); myx_bus_space_write(sc, - offset + sizeof(txd) * sc->sc_tx_ring_idx, &txd, + offset + sizeof(txd) * sc->sc_tx_ring_prod, &txd, sizeof(txd) - sizeof(myx_bus_t)); bus_space_barrier(sc->sc_memt, sc->sc_memh, offset, sizeof(txd) * sc->sc_tx_ring_count, BUS_SPACE_BARRIER_WRITE); myx_bus_space_write(sc, - offset + sizeof(txd) * (sc->sc_tx_ring_idx + 1) - sizeof(myx_bus_t), + offset + sizeof(txd) * (sc->sc_tx_ring_prod + 1) - + sizeof(myx_bus_t), (u_int8_t *)&txd + sizeof(txd) - sizeof(myx_bus_t), sizeof(myx_bus_t)); bus_space_barrier(sc->sc_memt, sc->sc_memh, - offset + sizeof(txd) * sc->sc_tx_ring_idx, sizeof(txd), + offset + sizeof(txd) * sc->sc_tx_ring_prod, sizeof(txd), BUS_SPACE_BARRIER_WRITE); /* commit */ - sc->sc_tx_ring_idx = idx; + sc->sc_tx_ring_prod = idx; sc->sc_tx_prod = prod; } @@ -1688,16 +1688,16 @@ myx_txeof(struct myx_softc *sc, u_int32_t done_count) struct ifnet *ifp = &sc->sc_ac.ac_if; struct myx_slot *ms; bus_dmamap_t map; - u_int free = 0; - u_int cons; + u_int idx, cons; + idx = sc->sc_tx_ring_cons; cons = sc->sc_tx_cons; do { ms = &sc->sc_tx_slots[cons]; map = ms->ms_map; - free += map->dm_nsegs + (map->dm_mapsize < 60 ? 1 : 0); + idx += map->dm_nsegs + (map->dm_mapsize < 60 ? 1 : 0); bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, BUS_DMASYNC_POSTWRITE); @@ -1710,6 +1710,10 @@ myx_txeof(struct myx_softc *sc, u_int32_t done_count) cons = 0; } while (++sc->sc_tx_count != done_count); + if (idx >= sc->sc_tx_ring_count) + idx -= sc->sc_tx_ring_count; + + sc->sc_tx_ring_cons = idx; sc->sc_tx_cons = cons; } |