summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2013-01-14 06:00:49 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2013-01-14 06:00:49 +0000
commitdcc851ca980953f9d4bd678c3b578951cc387ce8 (patch)
treeb22c8d9b8d3c3247babeb422e823510c80520571 /sys
parenta7e59cad598affb623897fa42245e63b2841e4a5 (diff)
when posting descriptors to the chips rings, avoid going write barrier
write barrier write barrier when using myx_write to post descriptors. instead let its go write write write barrier by using the appropriate bus_space write directly followed by a single bus_space barrier. the story above is mostly true, except that myx wants use to write all the descriptors except the first, barrier, and then write the first one out to signale that the chip can proceed. it is also worth noting that the barriers cover more address space than what we actually wrote to. this makes the code much simpler, and avoids generating extra fence operations (which is what barrier functions end up as on most of our archs) when we wrap around the end of the ring. the bus_space doco encourages this. bus_space use was discussed with krw@ kettenis@ deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_myx.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/sys/dev/pci/if_myx.c b/sys/dev/pci/if_myx.c
index 89e064f8d2b..6cd0d55dc1a 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.33 2013/01/14 04:02:02 dlg Exp $ */
+/* $OpenBSD: if_myx.c,v 1.34 2013/01/14 06:00:48 dlg Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org>
@@ -1385,7 +1385,8 @@ myx_write_txd_head(struct myx_softc *sc, struct myx_buf *mb, u_int8_t flags,
txd.tx_nsegs = map->dm_nsegs + (map->dm_mapsize < 60 ? 1 : 0);
txd.tx_flags = flags | MYXTXD_FLAGS_FIRST;
- myx_write(sc, offset + sizeof(txd) * idx, &txd, sizeof(txd));
+ bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh,
+ offset + sizeof(txd) * idx, &txd, sizeof(txd));
}
void
myx_write_txd_tail(struct myx_softc *sc, struct myx_buf *mb, u_int8_t flags,
@@ -1402,8 +1403,8 @@ myx_write_txd_tail(struct myx_softc *sc, struct myx_buf *mb, u_int8_t flags,
txd.tx_length = htobe16(map->dm_segs[i].ds_len);
txd.tx_flags = flags;
- myx_write(sc, offset +
- sizeof(txd) * ((idx + i) % sc->sc_tx_ring_count),
+ bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh,
+ offset + sizeof(txd) * ((idx + i) % sc->sc_tx_ring_count),
&txd, sizeof(txd));
}
@@ -1414,8 +1415,8 @@ myx_write_txd_tail(struct myx_softc *sc, struct myx_buf *mb, u_int8_t flags,
txd.tx_length = htobe16(60 - map->dm_mapsize);
txd.tx_flags = flags;
- myx_write(sc, offset +
- sizeof(txd) * ((idx + i) % sc->sc_tx_ring_count),
+ bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh,
+ offset + sizeof(txd) * ((idx + i) % sc->sc_tx_ring_count),
&txd, sizeof(txd));
}
}
@@ -1512,7 +1513,18 @@ myx_start(struct ifnet *ifp)
flags |= MYXTXD_FLAGS_SMALL;
myx_write_txd_tail(sc, firstmb, flags, offset, firstidx);
+
+ /* make sure the first descriptor is seen after the others */
+ if (idx != firstidx + 1) {
+ bus_space_barrier(sc->sc_memt, sc->sc_memh, offset,
+ sizeof(struct myx_tx_desc) * sc->sc_tx_ring_count,
+ BUS_SPACE_BARRIER_WRITE);
+ }
+
myx_write_txd_head(sc, firstmb, flags, offset, firstidx);
+ bus_space_barrier(sc->sc_memt, sc->sc_memh,
+ offset + sizeof(struct myx_tx_desc) * firstidx,
+ sizeof(struct myx_tx_desc), BUS_SPACE_BARRIER_WRITE);
}
int
@@ -1760,16 +1772,23 @@ myx_rx_fill(struct myx_softc *sc, int ring)
myx_buf_put(&sc->sc_rx_buf_list[ring], mb);
rxd.rx_addr = htobe64(mb->mb_map->dm_segs[0].ds_addr);
- myx_write(sc, offset + idx * sizeof(rxd),
- &rxd, sizeof(rxd));
+ bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh,
+ offset + idx * sizeof(rxd), &rxd, sizeof(rxd));
idx++;
idx %= sc->sc_rx_ring_count;
}
+ /* make sure the first descriptor is seen after the others */
+ if (idx != firstidx + 1) {
+ bus_space_barrier(sc->sc_memt, sc->sc_memh,
+ offset, sizeof(rxd) * sc->sc_rx_ring_count,
+ BUS_SPACE_BARRIER_WRITE);
+ }
+
rxd.rx_addr = htobe64(firstmb->mb_map->dm_segs[0].ds_addr);
myx_write(sc, offset + firstidx * sizeof(rxd),
- &rxd, sizeof(rxd));
+ &rxd, sizeof(rxd));
sc->sc_rx_ring_idx[ring] = idx;