Module Name:    src
Committed By:   sborrill
Date:           Fri Feb 24 17:45:29 UTC 2012

Modified Files:
        src/sys/arch/xen/xen [netbsd-5]: if_xennet_xenbus.c

Log Message:
Pull up the following revisions(s) (requested by bouyer in ticket #1730):
        sys/arch/xen/xen/if_xennet_xenbus.c:    revision 1.59 via patch

Fix receive stall on the domU side when buffers stay a long time in the
network stack or socket buffers.


To generate a diff of this commit:
cvs rdiff -u -r1.29.2.6 -r1.29.2.7 src/sys/arch/xen/xen/if_xennet_xenbus.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/arch/xen/xen/if_xennet_xenbus.c
diff -u src/sys/arch/xen/xen/if_xennet_xenbus.c:1.29.2.6 src/sys/arch/xen/xen/if_xennet_xenbus.c:1.29.2.7
--- src/sys/arch/xen/xen/if_xennet_xenbus.c:1.29.2.6	Thu May 19 21:13:07 2011
+++ src/sys/arch/xen/xen/if_xennet_xenbus.c	Fri Feb 24 17:45:29 2012
@@ -1,4 +1,4 @@
-/*      $NetBSD: if_xennet_xenbus.c,v 1.29.2.6 2011/05/19 21:13:07 bouyer Exp $      */
+/*      $NetBSD: if_xennet_xenbus.c,v 1.29.2.7 2012/02/24 17:45:29 sborrill Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_xennet_xenbus.c,v 1.29.2.6 2011/05/19 21:13:07 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_xennet_xenbus.c,v 1.29.2.7 2012/02/24 17:45:29 sborrill Exp $");
 
 #include "opt_xen.h"
 #include "opt_nfs_boot.h"
@@ -130,7 +130,6 @@ int xennet_debug = 0xff;
 #endif
 
 #define GRANT_INVALID_REF -1 /* entry is free */
-#define GRANT_STACK_REF   -2 /* entry owned by the network stack */
 
 #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
 #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
@@ -192,6 +191,9 @@ struct xennet_xenbus_softc {
 static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1];
 static u_long xennet_pages[NET_RX_RING_SIZE];
 
+static pool_cache_t if_xennetrxbuf_cache;
+static int if_xennetrxbuf_cache_inited=0;
+
 static int  xennet_xenbus_match(device_t, cfdata_t, void *);
 static void xennet_xenbus_attach(device_t, device_t, void *);
 static int  xennet_xenbus_detach(device_t, int);
@@ -202,6 +204,7 @@ static void xennet_alloc_rx_buffer(struc
 static void xennet_free_rx_buffer(struct xennet_xenbus_softc *);
 static void xennet_tx_complete(struct xennet_xenbus_softc *);
 static void xennet_rx_mbuf_free(struct mbuf *, void *, size_t, void *);
+static void xennet_rx_free_req(struct xennet_rxreq *);
 static int  xennet_handler(void *);
 static int  xennet_talk_to_backend(struct xennet_xenbus_softc *);
 #ifdef XENNET_DEBUG_DUMP
@@ -278,6 +281,14 @@ xennet_xenbus_attach(device_t parent, de
 	sc->sc_xbusd = xa->xa_xbusd;
 	sc->sc_xbusd->xbusd_otherend_changed = xennet_backend_changed;
 
+	/* xenbus ensure 2 devices can't be probed at the same time */
+	if (if_xennetrxbuf_cache_inited == 0) {
+		if_xennetrxbuf_cache = pool_cache_init(PAGE_SIZE, 0, 0, 0,
+		    "xnfrx", NULL, IPL_VM, NULL, NULL, NULL);
+		if_xennetrxbuf_cache_inited = 1;
+	}
+		
+
 	/* initialize free RX and RX request lists */
 	SLIST_INIT(&sc->sc_txreq_head);
 	for (i = 0; i < NET_TX_RING_SIZE; i++) {
@@ -291,13 +302,10 @@ xennet_xenbus_attach(device_t parent, de
 		struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i];
 		rxreq->rxreq_id = i;
 		rxreq->rxreq_sc = sc;
-		rxreq->rxreq_va = uvm_km_alloc(kernel_map,
-		    PAGE_SIZE, PAGE_SIZE, UVM_KMF_WIRED | UVM_KMF_ZERO);
+		rxreq->rxreq_va = (vaddr_t)pool_cache_get_paddr(
+		    if_xennetrxbuf_cache, PR_WAITOK, &rxreq->rxreq_pa);
 		if (rxreq->rxreq_va == 0)
 			break;
-		if (!pmap_extract(pmap_kernel(), rxreq->rxreq_va,
-		    &rxreq->rxreq_pa))
-			panic("%s: no pa for mapped va ?", device_xname(self));
 		rxreq->rxreq_gntref = GRANT_INVALID_REF;
 		SLIST_INSERT_HEAD(&sc->sc_rxreq_head, rxreq, rxreq_next);
 	}
@@ -560,7 +568,7 @@ xennet_alloc_rx_buffer(struct xennet_xen
 	RING_IDX i;
 	struct xennet_rxreq *req;
 	struct xen_memory_reservation reservation;
-	int s1, s2, otherend_id;
+	int s1, s2, otherend_id, notify;
 	paddr_t pfn;
 
 	otherend_id = sc->sc_xbusd->xbusd_otherend_id;
@@ -647,9 +655,10 @@ out_loop:
 	}
 
 	sc->sc_rx_ring.req_prod_pvt = req_prod + i;
-	RING_PUSH_REQUESTS(&sc->sc_rx_ring);
-
+	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_rx_ring, notify);
 	splx(s1);
+	if (notify)
+		hypervisor_notify_via_evtchn(sc->sc_evtchn);
 	return;
 }
 
@@ -669,14 +678,6 @@ xennet_free_rx_buffer(struct xennet_xenb
 	for (i = 0; i < NET_RX_RING_SIZE; i++) {
 		struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i];
 
-		/*
-		 * if the buffer is in transit in the network stack, wait for
-		 * the network stack to free it.
-		 */
-		while ((volatile grant_ref_t)rxreq->rxreq_gntref ==
-		    GRANT_STACK_REF)
-			tsleep(xennet_xenbus_detach, PRIBIO, "xnet_free", hz/2);
-
 		if (rxreq->rxreq_gntref != GRANT_INVALID_REF) {
 			/*
 			 * this req is still granted. Get back the page or
@@ -746,7 +747,20 @@ xennet_free_rx_buffer(struct xennet_xenb
 static void
 xennet_rx_mbuf_free(struct mbuf *m, void *buf, size_t size, void *arg)
 {
-	struct xennet_rxreq *req = arg;
+	int s = splnet();
+	KASSERT(buf == m->m_ext.ext_buf);
+	KASSERT(arg == NULL);
+	KASSERT(m != NULL);
+	vaddr_t va = (vaddr_t)(buf) & ~((vaddr_t)PAGE_MASK);
+	pool_cache_put_paddr(if_xennetrxbuf_cache,
+	    (void *)va, m->m_ext.ext_paddr);
+	pool_cache_put(mb_cache, m);
+	splx(s);
+};
+
+static void
+xennet_rx_free_req(struct xennet_rxreq *req)
+{
 	struct xennet_xenbus_softc *sc = req->rxreq_sc;
 
 	int s = splnet();
@@ -755,17 +769,15 @@ xennet_rx_mbuf_free(struct mbuf *m, void
 	sc->sc_free_rxreql++;
 
 	req->rxreq_gntref = GRANT_INVALID_REF;
-	if (sc->sc_free_rxreql >= SC_NLIVEREQ(sc) &&
+	
+	if (sc->sc_free_rxreql >= (NET_RX_RING_SIZE * 4 / 5) &&
 	    __predict_true(sc->sc_backend_status == BEST_CONNECTED)) {
 		xennet_alloc_rx_buffer(sc);
 	}
 
-	if (m)
-		pool_cache_put(mb_cache, m);
 	splx(s);
 }
 
-
 static void
 xennet_tx_complete(struct xennet_xenbus_softc *sc)
 {
@@ -879,8 +891,6 @@ again:
 			    __func__, sc->sc_rx_feature);			
 		}
 
-		req->rxreq_gntref = GRANT_INVALID_REF;
-
 		pa = req->rxreq_pa;
 		va = req->rxreq_va;
 
@@ -912,8 +922,7 @@ again:
 				DPRINTFN(XEDB_EVENT,
 				    ("xennet_handler bad dest\n"));
 				/* packet not for us */
-				xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE,
-				    req);
+				xennet_rx_free_req(req);
 				continue;
 			}
 		}
@@ -921,36 +930,28 @@ again:
 		if (__predict_false(m == NULL)) {
 			printf("xennet: rx no mbuf\n");
 			ifp->if_ierrors++;
-			xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, req);
+			xennet_rx_free_req(req);
 			continue;
 		}
 		MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
 
 		m->m_pkthdr.rcvif = ifp;
-		if (__predict_true(sc->sc_rx_ring.req_prod_pvt != 
-		    sc->sc_rx_ring.sring->rsp_prod)) {
-			m->m_len = m->m_pkthdr.len = rx->status;
-			MEXTADD(m, pktp, rx->status,
-			    M_DEVBUF, xennet_rx_mbuf_free, req);
-			m->m_flags |= M_EXT_RW; /* we own the buffer */
-			req->rxreq_gntref = GRANT_STACK_REF;
-		} else {
-			/*
-			 * This was our last receive buffer, allocate
-			 * memory, copy data and push the receive
-			 * buffer back to the hypervisor.
-			 */
-			m->m_len = min(MHLEN, rx->status);
-			m->m_pkthdr.len = 0;
-			m_copyback(m, 0, rx->status, pktp);
-			xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, req);
-			if (m->m_pkthdr.len < rx->status) {
-				/* out of memory, just drop packets */
-				ifp->if_ierrors++;
-				m_freem(m);
-				continue;
-			}
+		req->rxreq_va = (vaddr_t)pool_cache_get_paddr(
+		    if_xennetrxbuf_cache, PR_NOWAIT, &req->rxreq_pa);
+		if (__predict_false(req->rxreq_va == 0)) {
+			printf("%s: rx no buf\n", ifp->if_xname);
+			ifp->if_ierrors++;
+			req->rxreq_va = va;
+			req->rxreq_pa = pa;
+			xennet_rx_free_req(req);
+			m_freem(m);
+			continue;
 		}
+		m->m_len = m->m_pkthdr.len = rx->status;
+		MEXTADD(m, pktp, rx->status,
+		    M_DEVBUF, xennet_rx_mbuf_free, NULL);
+		m->m_flags |= M_EXT_RW; /* we own the buffer */
+		m->m_ext.ext_paddr = pa;
 		if ((rx->flags & NETRXF_csum_blank) != 0) {
 			xennet_checksum_fill(&m);
 			if (m == NULL) {
@@ -958,6 +959,8 @@ again:
 				continue;
 			}
 		}
+		/* free req may overwrite *rx, better doing it late */
+		xennet_rx_free_req(req);
 #if NBPFILTER > 0
 		/*
 		 * Pass packet to bpf if there is a listener.

Reply via email to