summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_myx.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2014-07-08 05:35:20 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2014-07-08 05:35:20 +0000
commit4930c61b730e44cdce66c7f71fa9f703fcae2b38 (patch)
tree69bcdb82287306b3e015c5b2778bccc9790f2f81 /sys/dev/pci/if_myx.c
parentf201a4bbc9d2fe8c3664f8b02ebf1ac13ae5b94e (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.c62
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);