diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2014-07-08 05:35:20 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2014-07-08 05:35:20 +0000 |
commit | 4930c61b730e44cdce66c7f71fa9f703fcae2b38 (patch) | |
tree | 69bcdb82287306b3e015c5b2778bccc9790f2f81 /sys/dev/pci/if_myx.c | |
parent | f201a4bbc9d2fe8c3664f8b02ebf1ac13ae5b94e (diff) |
cut things that relied on mclgeti for rx ring accounting/restriction over
to using if_rxr.
cut the reporting systat did over to the rxr ioctl.
tested as much as i can on alpha, amd64, and sparc64.
mpi@ has run it on macppc.
ok mpi@
Diffstat (limited to 'sys/dev/pci/if_myx.c')
-rw-r--r-- | sys/dev/pci/if_myx.c | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/sys/dev/pci/if_myx.c b/sys/dev/pci/if_myx.c index 0bfe70a5704..848e4854f81 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.58 2014/06/17 04:58:45 dlg Exp $ */ +/* $OpenBSD: if_myx.c,v 1.59 2014/07/08 05:35:18 dlg Exp $ */ /* * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org> @@ -143,6 +143,7 @@ struct myx_softc { struct myx_buf_list sc_rx_buf_free[2]; struct myx_buf_list sc_rx_buf_list[2]; u_int sc_rx_ring_idx[2]; + struct if_rxring sc_rx_ring[2]; #define MYX_RXSMALL 0 #define MYX_RXBIG 1 struct timeout sc_refill; @@ -195,6 +196,7 @@ void myx_media_status(struct ifnet *, struct ifmediareq *); void myx_link_state(struct myx_softc *, u_int32_t); void myx_watchdog(struct ifnet *); int myx_ioctl(struct ifnet *, u_long, caddr_t); +int myx_rxrinfo(struct myx_softc *, struct if_rxrinfo *); void myx_up(struct myx_softc *); void myx_iff(struct myx_softc *); void myx_down(struct myx_softc *); @@ -944,6 +946,10 @@ myx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); break; + case SIOCGIFRXR: + error = myx_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data); + break; + default: error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); } @@ -959,6 +965,26 @@ myx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) return (error); } +int +myx_rxrinfo(struct myx_softc *sc, struct if_rxrinfo *ifri) +{ + struct if_rxring_info ifr[2]; + + memset(ifr, 0, sizeof(ifr)); + + ifr[0].ifr_size = MCLBYTES; + mtx_enter(&sc->sc_rx_ring_lock[0].mrl_mtx); + ifr[0].ifr_info = sc->sc_rx_ring[0]; + mtx_leave(&sc->sc_rx_ring_lock[0].mrl_mtx); + + ifr[1].ifr_size = 12 * 1024; + mtx_enter(&sc->sc_rx_ring_lock[1].mrl_mtx); + ifr[1].ifr_info = sc->sc_rx_ring[1]; + mtx_leave(&sc->sc_rx_ring_lock[1].mrl_mtx); + + return (if_rxr_info_ioctl(ifri, nitems(ifr), ifr)); +} + void myx_up(struct myx_softc *sc) { @@ -1008,9 +1034,6 @@ myx_up(struct myx_softc *sc) } sc->sc_rx_ring_count = r / sizeof(struct myx_rx_desc); - m_clsetwms(ifp, MCLBYTES, 2, sc->sc_rx_ring_count - 2); - m_clsetwms(ifp, 12 * 1024, 2, sc->sc_rx_ring_count - 2); - memset(&mc, 0, sizeof(mc)); if (myx_cmd(sc, MYXCMD_GET_TXRINGSZ, &mc, &r) != 0) { printf("%s: unable to get tx ring size\n", DEVNAME(sc)); @@ -1177,6 +1200,9 @@ myx_up(struct myx_softc *sc) myx_buf_put(&sc->sc_rx_buf_free[MYX_RXBIG], mb); } + if_rxr_init(&sc->sc_rx_ring[MYX_RXBIG], 2, sc->sc_rx_ring_count - 2); + if_rxr_init(&sc->sc_rx_ring[MYX_RXSMALL], 2, sc->sc_rx_ring_count - 2); + myx_rx_zero(sc, MYX_RXSMALL); if (myx_rx_fill(sc, MYX_RXSMALL) != 0) { printf("%s: failed to fill small rx ring\n", DEVNAME(sc)); @@ -1777,6 +1803,7 @@ myx_rxeof(struct myx_softc *sc) struct mbuf *m; int ring; int rings = 0; + u_int rxfree[2] = { 0 , 0 }; u_int len; bus_dmamap_sync(sc->sc_dmat, sc->sc_intrq_dma.mxm_map, 0, @@ -1818,12 +1845,20 @@ myx_rxeof(struct myx_softc *sc) myx_buf_put(&sc->sc_rx_buf_free[ring], mb); - SET(rings, 1 << ring); + rxfree[ring]++; } bus_dmamap_sync(sc->sc_dmat, sc->sc_intrq_dma.mxm_map, 0, sc->sc_intrq_dma.mxm_map->dm_mapsize, BUS_DMASYNC_PREREAD); + for (ring = MYX_RXSMALL; ring <= MYX_RXBIG; ring++) { + mtx_enter(&sc->sc_rx_ring_lock[ring].mrl_mtx); + if_rxr_put(&sc->sc_rx_ring[ring], rxfree[ring]); + mtx_leave(&sc->sc_rx_ring_lock[ring].mrl_mtx); + + SET(rings, 1 << ring); + } + return (rings); } @@ -1849,13 +1884,20 @@ myx_rx_fill(struct myx_softc *sc, int ring) struct myx_rx_desc rxd; struct myx_buf *mb, *firstmb; u_int32_t offset = sc->sc_rx_ring_offset[ring]; - u_int idx, firstidx; + u_int idx, firstidx, slots; int rv = 1; if (!myx_ring_enter(&sc->sc_rx_ring_lock[ring])) return (-1); do { + mtx_enter(&sc->sc_rx_ring_lock[ring].mrl_mtx); + slots = if_rxr_get(&sc->sc_rx_ring[ring], sc->sc_rx_ring_count); + mtx_leave(&sc->sc_rx_ring_lock[ring].mrl_mtx); + + if (slots-- == 0) + continue; + firstmb = myx_buf_fill(sc, ring); if (firstmb == NULL) continue; @@ -1867,7 +1909,7 @@ myx_rx_fill(struct myx_softc *sc, int ring) idx = firstidx + 1; idx %= sc->sc_rx_ring_count; - while ((mb = myx_buf_fill(sc, ring)) != NULL) { + while (slots > 0 && (mb = myx_buf_fill(sc, ring)) != NULL) { myx_buf_put(&sc->sc_rx_buf_list[ring], mb); rxd.rx_addr = htobe64(mb->mb_map->dm_segs[0].ds_addr); @@ -1876,6 +1918,7 @@ myx_rx_fill(struct myx_softc *sc, int ring) idx++; idx %= sc->sc_rx_ring_count; + slots--; } /* make sure the first descriptor is seen after the others */ @@ -1890,6 +1933,9 @@ myx_rx_fill(struct myx_softc *sc, int ring) &rxd, sizeof(rxd)); sc->sc_rx_ring_idx[ring] = idx; + mtx_enter(&sc->sc_rx_ring_lock[ring].mrl_mtx); + if_rxr_put(&sc->sc_rx_ring[ring], slots); + mtx_leave(&sc->sc_rx_ring_lock[ring].mrl_mtx); } while (!myx_ring_leave(&sc->sc_rx_ring_lock[ring])); return (rv); @@ -1904,7 +1950,7 @@ myx_buf_fill(struct myx_softc *sc, int ring) int rv; KERNEL_LOCK(); - m = MCLGETI(NULL, M_DONTWAIT, &sc->sc_ac.ac_if, sizes[ring]); + m = MCLGETI(NULL, M_DONTWAIT, NULL, sizes[ring]); KERNEL_UNLOCK(); if (m == NULL) return (NULL); |