summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_myx.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2015-11-24 10:04:35 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2015-11-24 10:04:35 +0000
commit1bef198472170a833f6871b702da2f4d423cc611 (patch)
treef13120bf3c616ae77b20966de9fbbb0157ba397d /sys/dev/pci/if_myx.c
parent59e72ac7b0a0a18ba6d12fc0eb00882b5073b2c4 (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.c44
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;
}