Some bus_dma(9)-related and memory allocation fixes:
- always bus_dmamap_unload() before recycling a receive descriptor - make sure to not sleep from interrupt context: call bus_dmamap_load with M_NOWAIT, and create dma maps BUS_DMA_ALLOCNOW. - if a receive descriptor has a NULL mbuf try to allocate a new one, don't try to receive it.
This commit is contained in:
parent
22637b9c37
commit
be340e279e
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_jme.c,v 1.16 2011/01/09 00:12:45 kochi Exp $ */
|
||||
/* $NetBSD: if_jme.c,v 1.17 2011/03/30 18:11:37 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Manuel Bouyer. All rights reserved.
|
||||
|
@ -58,7 +58,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_jme.c,v 1.16 2011/01/09 00:12:45 kochi Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_jme.c,v 1.17 2011/03/30 18:11:37 bouyer Exp $");
|
||||
|
||||
|
||||
#include <sys/param.h>
|
||||
|
@ -439,13 +439,14 @@ jme_pci_attach(device_t parent, device_t self, void *aux)
|
|||
for (i = 0; i < JME_NBUFS; i++) {
|
||||
sc->jme_txmbuf[i] = sc->jme_rxmbuf[i] = NULL;
|
||||
if (bus_dmamap_create(sc->jme_dmatag, JME_MAX_TX_LEN,
|
||||
JME_NBUFS, JME_MAX_TX_LEN, 0, BUS_DMA_NOWAIT,
|
||||
JME_NBUFS, JME_MAX_TX_LEN, 0,
|
||||
BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
|
||||
&sc->jme_txmbufm[i]) != 0) {
|
||||
aprint_error_dev(self, "can't allocate DMA TX map\n");
|
||||
return;
|
||||
}
|
||||
if (bus_dmamap_create(sc->jme_dmatag, JME_MAX_RX_LEN,
|
||||
1, JME_MAX_RX_LEN, 0, BUS_DMA_NOWAIT,
|
||||
1, JME_MAX_RX_LEN, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
|
||||
&sc->jme_rxmbufm[i]) != 0) {
|
||||
aprint_error_dev(self, "can't allocate DMA RX map\n");
|
||||
return;
|
||||
|
@ -706,6 +707,8 @@ jme_add_rxbuf(jme_softc_t *sc, struct mbuf *m)
|
|||
}
|
||||
map = sc->jme_rxmbufm[i];
|
||||
m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
|
||||
KASSERT(m->m_len == MCLBYTES);
|
||||
|
||||
error = bus_dmamap_load_mbuf(sc->jme_dmatag, map, m,
|
||||
BUS_DMA_READ|BUS_DMA_NOWAIT);
|
||||
if (error) {
|
||||
|
@ -1051,6 +1054,7 @@ jme_statchg(device_t self)
|
|||
static void
|
||||
jme_intr_rx(jme_softc_t *sc) {
|
||||
struct mbuf *m, *mhead;
|
||||
bus_dmamap_t mmap;
|
||||
struct ifnet *ifp = &sc->jme_if;
|
||||
uint32_t flags, buflen;
|
||||
int i, ipackets, nsegs, seg, error;
|
||||
|
@ -1072,11 +1076,19 @@ jme_intr_rx(jme_softc_t *sc) {
|
|||
printf("rxintr i %d flags 0x%x buflen 0x%x\n",
|
||||
i, le32toh(desc->flags), le32toh(desc->buflen));
|
||||
#endif
|
||||
if (sc->jme_rxmbuf[i] == NULL) {
|
||||
if ((error = jme_add_rxbuf(sc, NULL)) != 0) {
|
||||
aprint_error_dev(sc->jme_dev,
|
||||
"can't add new mbuf to empty slot: %d\n",
|
||||
error);
|
||||
break;
|
||||
}
|
||||
JME_DESC_INC(sc->jme_rx_cons, JME_NBUFS);
|
||||
i = sc->jme_rx_cons;
|
||||
continue;
|
||||
}
|
||||
if ((le32toh(desc->buflen) & JME_RD_VALID) == 0)
|
||||
break;
|
||||
bus_dmamap_sync(sc->jme_dmatag, sc->jme_rxmbufm[i], 0,
|
||||
sc->jme_rxmbufm[i]->dm_mapsize, BUS_DMASYNC_POSTREAD);
|
||||
bus_dmamap_unload(sc->jme_dmatag, sc->jme_rxmbufm[i]);
|
||||
|
||||
buflen = le32toh(desc->buflen);
|
||||
nsegs = JME_RX_NSEGS(buflen);
|
||||
|
@ -1094,6 +1106,10 @@ jme_intr_rx(jme_softc_t *sc) {
|
|||
for (seg = 0; seg < nsegs; seg++) {
|
||||
m = sc->jme_rxmbuf[i];
|
||||
sc->jme_rxmbuf[i] = NULL;
|
||||
mmap = sc->jme_rxmbufm[i];
|
||||
bus_dmamap_sync(sc->jme_dmatag, mmap, 0,
|
||||
mmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
|
||||
bus_dmamap_unload(sc->jme_dmatag, mmap);
|
||||
if ((error = jme_add_rxbuf(sc, m)) != 0)
|
||||
aprint_error_dev(sc->jme_dev,
|
||||
"can't reuse mbuf: %d\n", error);
|
||||
|
@ -1105,11 +1121,24 @@ jme_intr_rx(jme_softc_t *sc) {
|
|||
/* receive this packet */
|
||||
mhead = m = sc->jme_rxmbuf[i];
|
||||
sc->jme_rxmbuf[i] = NULL;
|
||||
mmap = sc->jme_rxmbufm[i];
|
||||
bus_dmamap_sync(sc->jme_dmatag, mmap, 0,
|
||||
mmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
|
||||
bus_dmamap_unload(sc->jme_dmatag, mmap);
|
||||
/* add a new buffer to chain */
|
||||
if (jme_add_rxbuf(sc, NULL) == ENOBUFS) {
|
||||
for (seg = 0; seg < nsegs; seg++) {
|
||||
if (jme_add_rxbuf(sc, NULL) != 0) {
|
||||
if ((error = jme_add_rxbuf(sc, m)) != 0)
|
||||
aprint_error_dev(sc->jme_dev,
|
||||
"can't reuse mbuf: %d\n", error);
|
||||
JME_DESC_INC(sc->jme_rx_cons, JME_NBUFS);
|
||||
i = sc->jme_rx_cons;
|
||||
for (seg = 1; seg < nsegs; seg++) {
|
||||
m = sc->jme_rxmbuf[i];
|
||||
sc->jme_rxmbuf[i] = NULL;
|
||||
mmap = sc->jme_rxmbufm[i];
|
||||
bus_dmamap_sync(sc->jme_dmatag, mmap, 0,
|
||||
mmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
|
||||
bus_dmamap_unload(sc->jme_dmatag, mmap);
|
||||
if ((error = jme_add_rxbuf(sc, m)) != 0)
|
||||
aprint_error_dev(sc->jme_dev,
|
||||
"can't reuse mbuf: %d\n", error);
|
||||
|
@ -1131,7 +1160,13 @@ jme_intr_rx(jme_softc_t *sc) {
|
|||
i = sc->jme_rx_cons;
|
||||
m = sc->jme_rxmbuf[i];
|
||||
sc->jme_rxmbuf[i] = NULL;
|
||||
(void)jme_add_rxbuf(sc, NULL);
|
||||
mmap = sc->jme_rxmbufm[i];
|
||||
bus_dmamap_sync(sc->jme_dmatag, mmap, 0,
|
||||
mmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
|
||||
bus_dmamap_unload(sc->jme_dmatag, mmap);
|
||||
if ((error = jme_add_rxbuf(sc, NULL)) != 0)
|
||||
aprint_error_dev(sc->jme_dev,
|
||||
"can't add new mbuf: %d\n", error);
|
||||
m->m_flags &= ~M_PKTHDR;
|
||||
m_cat(mhead, m);
|
||||
JME_DESC_INC(sc->jme_rx_cons, JME_NBUFS);
|
||||
|
@ -1425,7 +1460,7 @@ jme_encap(struct jme_softc *sc, struct mbuf **m_head)
|
|||
txd = &sc->jme_txring[prod];
|
||||
|
||||
error = bus_dmamap_load_mbuf(sc->jme_dmatag, sc->jme_txmbufm[prod],
|
||||
*m_head, BUS_DMA_WRITE);
|
||||
*m_head, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
|
||||
if (error) {
|
||||
if (error == EFBIG) {
|
||||
log(LOG_ERR, "%s: Tx packet consumes too many "
|
||||
|
|
Loading…
Reference in New Issue