- en_mfix shouldn't touch M_EXT mbufs.    change to avoid this [at
    the expense of allocating a new cluster mbuf to copy to].

    XXX: en_mfix is getting called more often than I hoped it would
    (seems to happen when TCP retransmits... we get all sorts of odd
    sized, odd lengthed data mbufs, yuck).    i may revise the xmit
    DMA code to use non-word sized dma.
This commit is contained in:
chuck 1996-07-11 22:48:10 +00:00
parent 9310a8c8aa
commit 6ae82431b5
2 changed files with 63 additions and 22 deletions

View File

@ -1,5 +1,5 @@
/* $NetBSD: midway.c,v 1.8 1996/07/11 00:15:56 chuck Exp $ */
/* (sync'd to midway.c 1.58) */
/* $NetBSD: midway.c,v 1.9 1996/07/11 22:48:10 chuck Exp $ */
/* (sync'd to midway.c 1.59) */
/*
*
@ -340,7 +340,7 @@ STATIC void en_init __P((struct en_softc *));
STATIC int en_ioctl __P((struct ifnet *, EN_IOCTL_CMDT, caddr_t));
STATIC int en_k2sz __P((int));
STATIC void en_loadvc __P((struct en_softc *, int));
STATIC void en_mfix __P((struct en_softc *, struct mbuf *));
STATIC int en_mfix __P((struct en_softc *, struct mbuf **, struct mbuf *));
STATIC struct mbuf *en_mget __P((struct en_softc *, u_int, u_int *));
STATIC int en_rxctl __P((struct en_softc *, struct atm_pseudoioctl *, int));
STATIC void en_txdma __P((struct en_softc *, int));
@ -663,7 +663,7 @@ done_probe:
sc->vtrash = sc->otrash = sc->mfix = sc->txmbovr = sc->dmaovr = 0;
sc->txoutspace = sc->txdtqout = sc->launch = sc->lheader = sc->ltail = 0;
sc->hwpull = sc->swadd = sc->rxqnotus = sc->rxqus = sc->rxoutboth = 0;
sc->rxdrqout = sc->ttrash = sc->rxmbufout = 0;
sc->rxdrqout = sc->ttrash = sc->rxmbufout = sc->mfixfail = 0;
#endif
sc->need_drqs = sc->need_dtqs = 0;
@ -1274,9 +1274,9 @@ struct ifnet *ifp;
{
struct en_softc *sc = (struct en_softc *) ifp->if_softc;
struct ifqueue *ifq = &ifp->if_snd; /* if INPUT QUEUE */
struct mbuf *m, *lastm;
struct mbuf *m, *lastm, *prev;
struct atm_pseudohdr *ap, *new_ap;
int txchan, c, mlen, got, need, toadd, cellcnt;
int txchan, c, mlen, got, need, toadd, cellcnt, first;
u_int32_t atm_vpi, atm_vci, atm_flags, *dat, aal;
u_int8_t *cp;
@ -1304,16 +1304,29 @@ struct ifnet *ifp;
lastm = m;
mlen = 0;
prev = NULL;
while (1) {
if ( (mtod(lastm, u_int) % sizeof(u_int32_t)) != 0 ||
((lastm->m_len % sizeof(u_int32_t)) != 0 && lastm->m_next))
en_mfix(sc, lastm);
((lastm->m_len % sizeof(u_int32_t)) != 0 && lastm->m_next)) {
first = (lastm == m);
if (en_mfix(sc, &lastm, prev) == 0) { /* failed? */
m_freem(m);
m = NULL;
break;
}
if (first)
m = lastm; /* update */
}
mlen += lastm->m_len;
if (lastm->m_next == NULL)
break;
prev = lastm;
lastm = lastm->m_next;
}
if (m == NULL) /* happens only if mfix fails */
continue;
ap = mtod(m, struct atm_pseudohdr *);
atm_vpi = ATM_PH_VPI(ap);
@ -1447,33 +1460,61 @@ struct ifnet *ifp;
* en_mfix: fix a stupid mbuf
*/
STATIC void en_mfix(sc, m)
STATIC int en_mfix(sc, mm, prev)
struct en_softc *sc;
struct mbuf *m;
struct mbuf **mm, *prev;
{
u_char *d = mtod(m, u_char *), *cp;
int off = ((u_int) d) % sizeof(u_int32_t);
struct mbuf *m, *new;
u_char *d, *cp;
int off;
struct mbuf *nxt;
m = *mm;
EN_COUNT(sc->mfix); /* count # of calls */
#ifdef EN_DEBUG
printf("%s: mfix mbuf m_data=0x%x, m_len=%d\n", sc->sc_dev.dv_xname,
m->m_data, m->m_len);
#endif
d = mtod(m, u_char *);
off = ((u_int) d) % sizeof(u_int32_t);
if (off) {
bcopy(d, d - off, m->m_len); /* ALIGN! (with costly data copy...) */
d -= off;
m->m_data = (caddr_t)d;
if ((m->m_flags & M_EXT) == 0) {
bcopy(d, d - off, m->m_len); /* ALIGN! (with costly data copy...) */
d -= off;
m->m_data = (caddr_t)d;
} else {
/* can't write to an M_EXT mbuf since it may be shared */
MGET(new, M_DONTWAIT, MT_DATA);
if (!new) {
EN_COUNT(sc->mfixfail);
return(0);
}
MCLGET(new, M_DONTWAIT);
if ((new->m_flags & M_EXT) == 0) {
m_free(new);
EN_COUNT(sc->mfixfail);
return(0);
}
bcopy(d, new->m_data, m->m_len); /* ALIGN! (with costly data copy...) */
new->m_len = m->m_len;
new->m_next = m->m_next;
if (prev)
prev->m_next = new;
m_free(m);
*mm = m = new; /* note: 'd' now invalid */
}
}
off = m->m_len % sizeof(u_int32_t);
if (off == 0)
return;
return(1);
d = d + m->m_len;
d = mtod(m, u_char *) + m->m_len;
off = sizeof(u_int32_t) - off;
nxt = m->m_next;
@ -1490,12 +1531,10 @@ struct mbuf *m;
nxt->m_len--;
nxt->m_data = (caddr_t)cp;
}
return;
return(1);
}
/*
* en_txdma: start trasmit DMA, if possible
*/
@ -2590,7 +2629,8 @@ int unit, level;
if (level & END_STATS) {
printf(" en_stats:\n");
printf(" %d mbufs fixed by mfix (should be zero)\n", sc->mfix);
printf(" %d mbufs fixed by mfix (%d failures)\n",
sc->mfix, sc->mfixfail);
printf(" %d rx dma overflow interrupts\n", sc->dmaovr);
printf(" %d times we ran out of TX space and stalled\n",
sc->txoutspace);

View File

@ -1,4 +1,4 @@
/* $NetBSD: midwayvar.h,v 1.5 1996/07/03 17:22:02 chuck Exp $ */
/* $NetBSD: midwayvar.h,v 1.6 1996/07/11 22:48:13 chuck Exp $ */
/*
*
@ -163,6 +163,7 @@ struct en_softc {
u_int32_t otrash; /* sw copy of counter */
u_int32_t ttrash; /* # of RBD's with T bit set */
u_int32_t mfix; /* # of times we had to call mfix */
u_int32_t mfixfail; /* # of times mfix failed */
u_int32_t txmbovr; /* # of times we dropped due to mbsize */
u_int32_t dmaovr; /* tx dma overflow count */
u_int32_t txoutspace; /* out of space in xmit buffer */