summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_myx.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2015-08-14 10:42:26 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2015-08-14 10:42:26 +0000
commitd24dff66f5f2515fb9c31dfd5fe8b55e35951867 (patch)
treeecd34729f7f54854b231544f6b79d0d7a98bc877 /sys/dev/pci/if_myx.c
parentd1d27c63c17b8ef14cd507f1bef748cfb6ececda (diff)
move to a per rx ring timeout for refilling empty rings.
this lets me get rid of the locking around the refilling of the rx ring. the timeout only runs refill if the rx ring is empty. we know rxeof wont try and refill it in that situation because there's no packets on the ring so we wont get interrupts for it. therefore we dont need to lock between the timeout and rxeof cos they cant run at the same time.
Diffstat (limited to 'sys/dev/pci/if_myx.c')
-rw-r--r--sys/dev/pci/if_myx.c135
1 files changed, 54 insertions, 81 deletions
diff --git a/sys/dev/pci/if_myx.c b/sys/dev/pci/if_myx.c
index 736ab54072d..f875acde003 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.79 2015/08/14 07:24:18 dlg Exp $ */
+/* $OpenBSD: if_myx.c,v 1.80 2015/08/14 10:42:25 dlg Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org>
@@ -93,22 +93,21 @@ struct myx_buf_list {
struct pool *myx_buf_pool;
struct pool *myx_mcl_pool;
-struct myx_ring_lock {
-};
-
struct myx_rx_slot {
bus_dmamap_t mrs_map;
struct mbuf *mrs_m;
};
struct myx_rx_ring {
- struct mutex mrr_rxr_mtx;
+ struct myx_softc *mrr_softc;
+ struct timeout mrr_refill;
struct if_rxring mrr_rxr;
+ struct myx_rx_slot *mrr_slots;
u_int32_t mrr_offset;
u_int mrr_running;
u_int mrr_prod;
u_int mrr_cons;
- struct myx_rx_slot *mrr_slots;
+ struct mbuf *(*mrr_mclget)(void);
};
enum myx_state {
@@ -153,7 +152,6 @@ struct myx_softc {
#define MYX_RXSMALL 0
#define MYX_RXBIG 1
struct myx_rx_ring sc_rx_ring[2];
- struct timeout sc_refill;
bus_size_t sc_tx_boundary;
u_int sc_tx_ring_count;
@@ -229,15 +227,15 @@ void myx_bufs_init(struct myx_buf_list *);
int myx_bufs_empty(struct myx_buf_list *);
struct myx_buf * myx_buf_get(struct myx_buf_list *);
void myx_buf_put(struct myx_buf_list *, struct myx_buf *);
-int myx_buf_fill(struct myx_softc *, int,
- struct myx_rx_slot *);
+int myx_buf_fill(struct myx_softc *, struct myx_rx_slot *,
+ struct mbuf *(*)(void));
struct mbuf * myx_mcl_small(void);
struct mbuf * myx_mcl_big(void);
int myx_rx_init(struct myx_softc *, int, bus_size_t);
-int myx_rx_fill(struct myx_softc *, int);
-void myx_rx_empty(struct myx_softc *, int);
-void myx_rx_free(struct myx_softc *, int);
+int myx_rx_fill(struct myx_softc *, struct myx_rx_ring *);
+void myx_rx_empty(struct myx_softc *, struct myx_rx_ring *);
+void myx_rx_free(struct myx_softc *, struct myx_rx_ring *);
void myx_refill(void *);
@@ -291,14 +289,18 @@ myx_attach(struct device *parent, struct device *self, void *aux)
sc->sc_tag = pa->pa_tag;
sc->sc_dmat = pa->pa_dmat;
- mtx_init(&sc->sc_rx_ring[MYX_RXSMALL].mrr_rxr_mtx, IPL_NET);
- mtx_init(&sc->sc_rx_ring[MYX_RXBIG].mrr_rxr_mtx, IPL_NET);
+ sc->sc_rx_ring[MYX_RXSMALL].mrr_softc = sc;
+ sc->sc_rx_ring[MYX_RXSMALL].mrr_mclget = myx_mcl_small;
+ timeout_set(&sc->sc_rx_ring[MYX_RXSMALL].mrr_refill, myx_refill,
+ &sc->sc_rx_ring[MYX_RXSMALL]);
+ sc->sc_rx_ring[MYX_RXBIG].mrr_softc = sc;
+ sc->sc_rx_ring[MYX_RXBIG].mrr_mclget = myx_mcl_big;
+ timeout_set(&sc->sc_rx_ring[MYX_RXBIG].mrr_refill, myx_refill,
+ &sc->sc_rx_ring[MYX_RXBIG]);
myx_bufs_init(&sc->sc_tx_buf_free);
myx_bufs_init(&sc->sc_tx_buf_list);
- timeout_set(&sc->sc_refill, myx_refill, sc);
-
mtx_init(&sc->sc_sts_mtx, IPL_NET);
/* Map the PCI memory space */
@@ -1020,14 +1022,10 @@ myx_rxrinfo(struct myx_softc *sc, struct if_rxrinfo *ifri)
memset(ifr, 0, sizeof(ifr));
ifr[0].ifr_size = MYX_RXSMALL_SIZE;
- mtx_enter(&sc->sc_rx_ring[MYX_RXSMALL].mrr_rxr_mtx);
ifr[0].ifr_info = sc->sc_rx_ring[0].mrr_rxr;
- mtx_leave(&sc->sc_rx_ring[MYX_RXSMALL].mrr_rxr_mtx);
ifr[1].ifr_size = MYX_RXBIG_SIZE;
- mtx_enter(&sc->sc_rx_ring[MYX_RXBIG].mrr_rxr_mtx);
ifr[1].ifr_info = sc->sc_rx_ring[1].mrr_rxr;
- mtx_leave(&sc->sc_rx_ring[MYX_RXBIG].mrr_rxr_mtx);
return (if_rxr_info_ioctl(ifri, nitems(ifr), ifr));
}
@@ -1234,13 +1232,13 @@ myx_up(struct myx_softc *sc)
if (myx_rx_init(sc, MYX_RXSMALL, MCLBYTES) != 0)
goto free_tx_bufs;
- if (myx_rx_fill(sc, MYX_RXSMALL) != 0)
+ if (myx_rx_fill(sc, &sc->sc_rx_ring[MYX_RXSMALL]) != 0)
goto free_rx_ring_small;
if (myx_rx_init(sc, MYX_RXBIG, MYX_RXBIG_SIZE) != 0)
goto empty_rx_ring_small;
- if (myx_rx_fill(sc, MYX_RXBIG) != 0)
+ if (myx_rx_fill(sc, &sc->sc_rx_ring[MYX_RXBIG]) != 0)
goto free_rx_ring_big;
memset(&mc, 0, sizeof(mc));
@@ -1274,13 +1272,13 @@ myx_up(struct myx_softc *sc)
return;
empty_rx_ring_big:
- myx_rx_empty(sc, MYX_RXBIG);
+ myx_rx_empty(sc, &sc->sc_rx_ring[MYX_RXBIG]);
free_rx_ring_big:
- myx_rx_free(sc, MYX_RXBIG);
+ myx_rx_free(sc, &sc->sc_rx_ring[MYX_RXBIG]);
empty_rx_ring_small:
- myx_rx_empty(sc, MYX_RXSMALL);
+ myx_rx_empty(sc, &sc->sc_rx_ring[MYX_RXSMALL]);
free_rx_ring_small:
- myx_rx_free(sc, MYX_RXSMALL);
+ myx_rx_free(sc, &sc->sc_rx_ring[MYX_RXSMALL]);
free_tx_bufs:
while ((mb = myx_buf_get(&sc->sc_tx_buf_free)) != NULL)
myx_buf_free(sc, mb);
@@ -1407,8 +1405,6 @@ myx_down(struct myx_softc *sc)
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
mtx_leave(&sc->sc_sts_mtx);
- timeout_del(&sc->sc_refill);
-
s = splnet();
if (ifp->if_link_state != LINK_STATE_UNKNOWN) {
ifp->if_link_state = LINK_STATE_UNKNOWN;
@@ -1425,8 +1421,11 @@ myx_down(struct myx_softc *sc)
CLR(ifp->if_flags, IFF_RUNNING | IFF_OACTIVE);
for (ring = 0; ring < 2; ring++) {
- myx_rx_empty(sc, ring);
- myx_rx_free(sc, ring);
+ struct myx_rx_ring *mrr = &sc->sc_rx_ring[ring];
+
+ timeout_del(&mrr->mrr_refill);
+ myx_rx_empty(sc, mrr);
+ myx_rx_free(sc, mrr);
}
while ((mb = myx_buf_get(&sc->sc_tx_buf_list)) != NULL) {
@@ -1729,19 +1728,15 @@ myx_intr(void *arg)
}
void
-myx_refill(void *xsc)
+myx_refill(void *xmrr)
{
- struct myx_softc *sc = xsc;
- struct myx_rx_ring *mrr;
- int ring;
+ struct myx_rx_ring *mrr = xmrr;
+ struct myx_softc *sc = mrr->mrr_softc;
- for (ring = 0; ring < 2; ring++) {
- mrr = &sc->sc_rx_ring[ring];
+ myx_rx_fill(sc, mrr);
- if (myx_rx_fill(sc, ring) >= 0 &&
- mrr->mrr_prod == mrr->mrr_cons)
- timeout_add(&sc->sc_refill, 1);
- }
+ if (mrr->mrr_prod == mrr->mrr_cons)
+ timeout_add(&mrr->mrr_refill, 1);
}
void
@@ -1832,29 +1827,25 @@ myx_rxeof(struct myx_softc *sc)
mrr = &sc->sc_rx_ring[ring];
- mtx_enter(&mrr->mrr_rxr_mtx);
if_rxr_put(&mrr->mrr_rxr, rxfree[ring]);
- mtx_leave(&mrr->mrr_rxr_mtx);
-
- if (myx_rx_fill(sc, ring) >= 0 &&
- mrr->mrr_prod == mrr->mrr_cons)
- timeout_add(&sc->sc_refill, 0);
+ myx_rx_fill(sc, mrr);
+ if (mrr->mrr_prod == mrr->mrr_cons)
+ timeout_add(&mrr->mrr_refill, 0);
}
if_input(ifp, &ml);
}
static int
-myx_rx_fill_slots(struct myx_softc *sc, int ring, u_int slots)
+myx_rx_fill_slots(struct myx_softc *sc, struct myx_rx_ring *mrr, u_int slots)
{
struct myx_rx_desc rxd;
- struct myx_rx_ring *mrr = &sc->sc_rx_ring[ring];
struct myx_rx_slot *mrs;
u_int32_t offset = mrr->mrr_offset;
u_int p, first, fills;
first = p = mrr->mrr_prod;
- if (myx_buf_fill(sc, ring, &mrr->mrr_slots[first]) != 0)
+ if (myx_buf_fill(sc, &mrr->mrr_slots[first], mrr->mrr_mclget) != 0)
return (slots);
if (++p >= sc->sc_rx_ring_count)
@@ -1863,7 +1854,7 @@ myx_rx_fill_slots(struct myx_softc *sc, int ring, u_int slots)
for (fills = 1; fills < slots; fills++) {
mrs = &mrr->mrr_slots[p];
- if (myx_buf_fill(sc, ring, mrs) != 0)
+ if (myx_buf_fill(sc, mrs, mrr->mrr_mclget) != 0)
break;
rxd.rx_addr = htobe64(mrs->mrs_map->dm_segs[0].ds_addr);
@@ -1950,41 +1941,24 @@ myx_rx_ring_leave(struct myx_rx_ring *mrr)
}
int
-myx_rx_fill(struct myx_softc *sc, int ring)
+myx_rx_fill(struct myx_softc *sc, struct myx_rx_ring *mrr)
{
- struct myx_rx_ring *mrr = &sc->sc_rx_ring[ring];
u_int slots;
- int rv = 1;
-
- if (!myx_rx_ring_enter(mrr))
- return (-1);
-
- do {
- mtx_enter(&sc->sc_rx_ring[ring].mrr_rxr_mtx);
- slots = if_rxr_get(&sc->sc_rx_ring[ring].mrr_rxr,
- sc->sc_rx_ring_count);
- mtx_leave(&sc->sc_rx_ring[ring].mrr_rxr_mtx);
-
- if (slots == 0)
- continue;
- slots = myx_rx_fill_slots(sc, ring, slots);
- rv = 0;
+ slots = if_rxr_get(&mrr->mrr_rxr, sc->sc_rx_ring_count);
+ if (slots == 0)
+ return (1);
- if (slots > 0) {
- mtx_enter(&sc->sc_rx_ring[ring].mrr_rxr_mtx);
- if_rxr_put(&sc->sc_rx_ring[ring].mrr_rxr, slots);
- mtx_leave(&sc->sc_rx_ring[ring].mrr_rxr_mtx);
- }
- } while (!myx_rx_ring_leave(mrr));
+ slots = myx_rx_fill_slots(sc, mrr, slots);
+ if (slots > 0)
+ if_rxr_put(&mrr->mrr_rxr, slots);
- return (rv);
+ return (0);
}
void
-myx_rx_empty(struct myx_softc *sc, int ring)
+myx_rx_empty(struct myx_softc *sc, struct myx_rx_ring *mrr)
{
- struct myx_rx_ring *mrr = &sc->sc_rx_ring[ring];
struct myx_rx_slot *mrs;
while (mrr->mrr_cons != mrr->mrr_prod) {
@@ -2003,9 +1977,8 @@ myx_rx_empty(struct myx_softc *sc, int ring)
}
void
-myx_rx_free(struct myx_softc *sc, int ring)
+myx_rx_free(struct myx_softc *sc, struct myx_rx_ring *mrr)
{
- struct myx_rx_ring *mrr = &sc->sc_rx_ring[ring];
struct myx_rx_slot *mrs;
int i;
@@ -2054,13 +2027,13 @@ myx_mcl_big(void)
}
int
-myx_buf_fill(struct myx_softc *sc, int ring, struct myx_rx_slot *mrs)
+myx_buf_fill(struct myx_softc *sc, struct myx_rx_slot *mrs,
+ struct mbuf *(*mclget)(void))
{
- struct mbuf *(*mclget[2])(void) = { myx_mcl_small, myx_mcl_big };
struct mbuf *m;
int rv;
- m = (*mclget[ring])();
+ m = (*mclget)();
if (m == NULL)
return (ENOMEM);