Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci add callout for re-filling RX ring - it's invoke...
details: https://anonhg.NetBSD.org/src/rev/2e5fe0c63c93
branches: trunk
changeset: 363091:2e5fe0c63c93
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Tue Jul 10 18:32:25 2018 +0000
description:
add callout for re-filling RX ring - it's invoked when the RX refill
code can't get enough buffers; fixes possible stall when the RXSTAT
interrupt arrives while no buffers are available
idea from OpenBSD if_msk.c rev. 1.131
as part of this remove the confusingly commented re-fill code from
msk_jfree() and instead just invoke the callout if needed; also
refill in msk_intr() only when running low instead of every RX intr;
this simplifies the code, and gives small RX performance boost on
my hardware (6%: ~38 MB/s -> ~40 MB/s)
tested on SK-9E22 (Yukon-2 XL rev. A3) by me, and 88E8071 (Yukon-2
Extreme rev. B0) by Jogn Halfpenny; unfortunately still doesn't
resolve the PR kern/53301 stall
diffstat:
sys/dev/pci/if_msk.c | 127 ++++++++++++++++++++++++++------------------------
1 files changed, 66 insertions(+), 61 deletions(-)
diffs (222 lines):
diff -r b8882c858ddb -r 2e5fe0c63c93 sys/dev/pci/if_msk.c
--- a/sys/dev/pci/if_msk.c Tue Jul 10 17:36:38 2018 +0000
+++ b/sys/dev/pci/if_msk.c Tue Jul 10 18:32:25 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_msk.c,v 1.71 2018/07/04 19:26:09 jdolecek Exp $ */
+/* $NetBSD: if_msk.c,v 1.72 2018/07/10 18:32:25 jdolecek Exp $ */
/* $OpenBSD: if_msk.c,v 1.79 2009/10/15 17:54:56 deraadt Exp $ */
/*
@@ -52,7 +52,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1.71 2018/07/04 19:26:09 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1.72 2018/07/10 18:32:25 jdolecek Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -114,7 +114,7 @@
void msk_init_yukon(struct sk_if_softc *);
void msk_stop(struct ifnet *, int);
void msk_watchdog(struct ifnet *);
-int msk_newbuf(struct sk_if_softc *, struct mbuf *, bus_dmamap_t);
+int msk_newbuf(struct sk_if_softc *, bus_dmamap_t);
int msk_alloc_jumbo_mem(struct sk_if_softc *);
void *msk_jalloc(struct sk_if_softc *);
void msk_jfree(struct mbuf *, void *, size_t, void *);
@@ -131,6 +131,7 @@
void msk_setmulti(struct sk_if_softc *);
void msk_setpromisc(struct sk_if_softc *);
void msk_tick(void *);
+static void msk_fill_rx_tick(void *);
/* #define MSK_DEBUG 1 */
#ifdef MSK_DEBUG
@@ -473,42 +474,30 @@
}
int
-msk_newbuf(struct sk_if_softc *sc_if, struct mbuf *m,
- bus_dmamap_t dmamap)
+msk_newbuf(struct sk_if_softc *sc_if, bus_dmamap_t dmamap)
{
struct mbuf *m_new = NULL;
struct sk_chain *c;
struct msk_rx_desc *r;
-
- if (m == NULL) {
- void *buf = NULL;
-
- MGETHDR(m_new, M_DONTWAIT, MT_DATA);
- if (m_new == NULL)
- return (ENOBUFS);
-
- /* Allocate the jumbo buffer */
- buf = msk_jalloc(sc_if);
- if (buf == NULL) {
- m_freem(m_new);
- DPRINTFN(1, ("%s jumbo allocation failed -- packet "
- "dropped!\n", sc_if->sk_ethercom.ec_if.if_xname));
- return (ENOBUFS);
- }
-
- /* Attach the buffer to the mbuf */
- m_new->m_len = m_new->m_pkthdr.len = SK_JLEN;
- MEXTADD(m_new, buf, SK_JLEN, 0, msk_jfree, sc_if);
- } else {
- /*
- * We're re-using a previously allocated mbuf;
- * be sure to re-init pointers and lengths to
- * default values.
- */
- m_new = m;
- m_new->m_len = m_new->m_pkthdr.len = SK_JLEN;
- m_new->m_data = m_new->m_ext.ext_buf;
+ void *buf = NULL;
+
+ MGETHDR(m_new, M_DONTWAIT, MT_DATA);
+ if (m_new == NULL)
+ return (ENOBUFS);
+
+ /* Allocate the jumbo buffer */
+ buf = msk_jalloc(sc_if);
+ if (buf == NULL) {
+ m_freem(m_new);
+ DPRINTFN(1, ("%s jumbo allocation failed -- packet "
+ "dropped!\n", sc_if->sk_ethercom.ec_if.if_xname));
+ return (ENOBUFS);
}
+
+ /* Attach the buffer to the mbuf */
+ m_new->m_len = m_new->m_pkthdr.len = SK_JLEN;
+ MEXTADD(m_new, buf, SK_JLEN, 0, msk_jfree, sc_if);
+
m_adj(m_new, ETHER_ALIGN);
c = &sc_if->sk_cdata.sk_rx_chain[sc_if->sk_cdata.sk_rx_prod];
@@ -697,6 +686,11 @@
if (__predict_true(m != NULL))
pool_cache_put(mb_cache, m);
+
+ /* Now that we know we have a free RX buffer, refill if running out */
+ if ((sc->sk_ethercom.ec_if.if_flags & IFF_RUNNING) != 0
+ && sc->sk_cdata.sk_rx_cnt < (MSK_RX_RING_CNT/3))
+ callout_schedule(&sc->sk_tick_rx, 0);
}
int
@@ -1202,6 +1196,9 @@
callout_setfunc(&sc_if->sk_tick_ch, msk_tick, sc_if);
callout_schedule(&sc_if->sk_tick_ch, hz);
+ callout_init(&sc_if->sk_tick_rx, 0);
+ callout_setfunc(&sc_if->sk_tick_rx, msk_fill_rx_tick, sc_if);
+
/*
* Call MI attach routines.
*/
@@ -1250,6 +1247,9 @@
callout_halt(&sc_if->sk_tick_ch, NULL);
callout_destroy(&sc_if->sk_tick_ch);
+ callout_halt(&sc_if->sk_tick_rx, NULL);
+ callout_destroy(&sc_if->sk_tick_rx);
+
/* Detach any PHYs we might have. */
if (LIST_FIRST(&sc_if->sk_mii.mii_phys) != NULL)
mii_detach(&sc_if->sk_mii, MII_PHY_ANY, MII_OFFSET_ANY);
@@ -1954,31 +1954,12 @@
total_len > ETHER_MAX_LEN_JUMBO ||
msk_rxvalid(sc, rxstat, total_len) == 0) {
ifp->if_ierrors++;
- msk_newbuf(sc_if, m, dmamap);
+ m_freem(m);
return;
}
- /*
- * Try to allocate a new jumbo buffer. If that fails, copy the
- * packet to mbufs and put the jumbo buffer back in the ring
- * so it can be re-used. If allocating mbufs fails, then we
- * have to drop the packet.
- */
- if (msk_newbuf(sc_if, NULL, dmamap) == ENOBUFS) {
- struct mbuf *m0;
- m0 = m_devget(mtod(m, char *) - ETHER_ALIGN,
- total_len + ETHER_ALIGN, 0, ifp, NULL);
- msk_newbuf(sc_if, m, dmamap);
- if (m0 == NULL) {
- ifp->if_ierrors++;
- return;
- }
- m_adj(m0, ETHER_ALIGN);
- m = m0;
- } else {
- m_set_rcvif(m, ifp);
- m->m_pkthdr.len = m->m_len = total_len;
- }
+ m_set_rcvif(m, ifp);
+ m->m_pkthdr.len = m->m_len = total_len;
/* pass it on. */
if_percpuq_enqueue(ifp->if_percpuq, m);
@@ -2047,11 +2028,35 @@
{
/* Make sure to not completely wrap around */
while (sc_if->sk_cdata.sk_rx_cnt < (MSK_RX_RING_CNT - 1)) {
- if (msk_newbuf(sc_if, NULL,
+ if (msk_newbuf(sc_if,
sc_if->sk_cdata.sk_rx_jumbo_map) == ENOBUFS) {
- break;
+ goto schedretry;
}
}
+
+ return;
+
+schedretry:
+ /* Try later */
+ callout_schedule(&sc_if->sk_tick_rx, hz/2);
+}
+
+static void
+msk_fill_rx_tick(void *xsc_if)
+{
+ struct sk_if_softc *sc_if = xsc_if;
+ int s, rx_prod;
+
+ KASSERT(KERNEL_LOCKED_P()); /* XXXSMP */
+
+ s = splnet();
+ rx_prod = sc_if->sk_cdata.sk_rx_prod;
+ msk_fill_rx_ring(sc_if);
+ if (rx_prod != sc_if->sk_cdata.sk_rx_prod) {
+ SK_IF_WRITE_2(sc_if, 0, SK_RXQ1_Y2_PREF_PUTIDX,
+ sc_if->sk_cdata.sk_rx_prod);
+ }
+ splx(s);
}
void
@@ -2136,9 +2141,8 @@
sc_if = sc->sk_if[cur_st->sk_link & 0x01];
msk_rxeof(sc_if, letoh16(cur_st->sk_len),
letoh32(cur_st->sk_status));
- msk_fill_rx_ring(sc_if);
- SK_IF_WRITE_2(sc_if, 0, SK_RXQ1_Y2_PREF_PUTIDX,
- sc_if->sk_cdata.sk_rx_prod);
+ if (sc_if->sk_cdata.sk_rx_cnt < (MSK_RX_RING_CNT/3))
+ msk_fill_rx_tick(sc_if);
break;
case SK_Y2_STOPC_TXSTAT:
if (sc_if0)
@@ -2471,6 +2475,7 @@
DPRINTFN(2, ("msk_stop\n"));
callout_stop(&sc_if->sk_tick_ch);
+ callout_stop(&sc_if->sk_tick_rx);
ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
Home |
Main Index |
Thread Index |
Old Index