summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2008-03-22 18:13:39 +0000
committerqingli <qingli@FreeBSD.org>2008-03-22 18:13:39 +0000
commit4471734ac457de960432db5260db6d2ab27ee28c (patch)
treecd5539642acb084218ab21c2eaa8cec3899c3cfe
parent599685413335ea56fc37494adb6852b0f049c9a6 (diff)
downloadFreeBSD-src-4471734ac457de960432db5260db6d2ab27ee28c.zip
FreeBSD-src-4471734ac457de960432db5260db6d2ab27ee28c.tar.gz
Reuse the mbuf that was just retrieved from the receive ring if mbuf
exhaustion is encountered. There was a fix made previously for this problem but the solution (breaking out of the receive loop) does not seem to work. mbuf reuse strategy is already adopted by other drivers such as if_bge. The problem was recreated and the patch is also verified in the same test environment.
-rw-r--r--sys/dev/fxp/if_fxp.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index a652fb6..e4bb212 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -231,7 +231,7 @@ static int fxp_ioctl(struct ifnet *ifp, u_long command,
caddr_t data);
static void fxp_watchdog(struct fxp_softc *sc);
static int fxp_add_rfabuf(struct fxp_softc *sc,
- struct fxp_rx *rxp);
+ struct fxp_rx *rxp, struct mbuf *oldm);
static int fxp_mc_addrs(struct fxp_softc *sc);
static void fxp_mc_setup(struct fxp_softc *sc);
static uint16_t fxp_eeprom_getword(struct fxp_softc *sc, int offset,
@@ -715,7 +715,7 @@ fxp_attach(device_t dev)
device_printf(dev, "can't create DMA map for RX\n");
goto fail;
}
- if (fxp_add_rfabuf(sc, rxp) != 0) {
+ if (fxp_add_rfabuf(sc, rxp, NULL) != 0) {
error = ENOMEM;
goto fail;
}
@@ -1652,7 +1652,7 @@ fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp, uint8_t statack,
* If this fails, the old buffer is recycled
* instead.
*/
- fxp_rc = fxp_add_rfabuf(sc, rxp);
+ fxp_rc = fxp_add_rfabuf(sc, rxp, m);
if (fxp_rc == 0) {
int total_len;
@@ -2245,17 +2245,26 @@ fxp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
* data pointer is fixed up to point just past it.
*/
static int
-fxp_add_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp)
+fxp_add_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp, struct mbuf *oldm)
{
struct mbuf *m;
struct fxp_rfa *rfa, *p_rfa;
struct fxp_rx *p_rx;
bus_dmamap_t tmp_map;
- int error;
+ int error, reused_mbuf=0;
m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- if (m == NULL)
- return (ENOBUFS);
+ if (m == NULL) {
+ if (oldm == NULL)
+ return ENOBUFS;
+ m = oldm;
+ m->m_data = m->m_ext.ext_buf;
+ /*
+ * return error so the receive loop will
+ * not pass the packet to upper layer
+ */
+ reused_mbuf = EAGAIN;
+ }
/*
* Move the data pointer up so that the incoming data packet
@@ -2320,7 +2329,7 @@ fxp_add_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp)
sc->fxp_desc.rx_head = rxp;
}
sc->fxp_desc.rx_tail = rxp;
- return (0);
+ return (reused_mbuf);
}
static int
OpenPOWER on IntegriCloud