Module Name:    src
Committed By:   bouyer
Date:           Wed Mar 30 18:11:37 UTC 2011

Modified Files:
        src/sys/dev/pci: if_jme.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/pci/if_jme.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/if_jme.c
diff -u src/sys/dev/pci/if_jme.c:1.16 src/sys/dev/pci/if_jme.c:1.17
--- src/sys/dev/pci/if_jme.c:1.16	Sun Jan  9 00:12:45 2011
+++ src/sys/dev/pci/if_jme.c	Wed Mar 30 18:11:37 2011
@@ -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 @@
 	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 @@
 	}
 	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 @@
 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;
@@ -1064,7 +1068,7 @@
 	    sc->jme_rx_cons, le32toh(sc->jme_rxring[sc->jme_rx_cons].flags));
 #endif
 	ipackets = 0;
-	while((le32toh(sc->jme_rxring[ sc->jme_rx_cons].flags) & JME_RD_OWN)
+	while((le32toh(sc->jme_rxring[sc->jme_rx_cons].flags) & JME_RD_OWN)
 	    == 0) {
 		i = sc->jme_rx_cons;
 		desc = &sc->jme_rxring[i];
@@ -1072,11 +1076,19 @@
 		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 @@
 			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 @@
 		/* 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 @@
 			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 @@
 	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 "

Reply via email to