diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2013-01-14 06:00:49 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2013-01-14 06:00:49 +0000 |
commit | dcc851ca980953f9d4bd678c3b578951cc387ce8 (patch) | |
tree | b22c8d9b8d3c3247babeb422e823510c80520571 /sys | |
parent | a7e59cad598affb623897fa42245e63b2841e4a5 (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.c | 37 |
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; |