Module Name:    src
Committed By:   jmcneill
Date:           Thu Aug  7 02:28:52 UTC 2014

Modified Files:
        src/sys/dev/pci: if_wpi.c if_wpivar.h

Log Message:
simplify wpi_rx_intr rbuf handling and add some more bus_dmamap_sync; fixes 
stalls when downloading large files for me


To generate a diff of this commit:
cvs rdiff -u -r1.64 -r1.65 src/sys/dev/pci/if_wpi.c
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/pci/if_wpivar.h

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_wpi.c
diff -u src/sys/dev/pci/if_wpi.c:1.64 src/sys/dev/pci/if_wpi.c:1.65
--- src/sys/dev/pci/if_wpi.c:1.64	Tue Aug  5 21:54:39 2014
+++ src/sys/dev/pci/if_wpi.c	Thu Aug  7 02:28:52 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wpi.c,v 1.64 2014/08/05 21:54:39 jmcneill Exp $	*/
+/*	$NetBSD: if_wpi.c,v 1.65 2014/08/07 02:28:52 jmcneill Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.64 2014/08/05 21:54:39 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.65 2014/08/07 02:28:52 jmcneill Exp $");
 
 /*
  * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
@@ -536,7 +536,6 @@ wpi_alloc_rbuf(struct wpi_softc *sc)
 	rbuf = SLIST_FIRST(&sc->rxq.freelist);
 	if (rbuf != NULL) {
 		SLIST_REMOVE_HEAD(&sc->rxq.freelist, next);
-		sc->rxq.nb_free_entries --;
 	}
 	mutex_exit(&sc->rxq.freelist_mtx);
 
@@ -558,8 +557,6 @@ wpi_free_rbuf(struct mbuf* m, void *buf,
 	mutex_enter(&sc->rxq.freelist_mtx);
 	SLIST_INSERT_HEAD(&sc->rxq.freelist, rbuf, next);
 	mutex_exit(&sc->rxq.freelist_mtx);
-	/* No need to protect this with a mutex, see wpi_rx_intr */
-	sc->rxq.nb_free_entries ++;
 
 	if (__predict_true(m != NULL))
 		pool_cache_put(mb_cache, m);
@@ -593,7 +590,6 @@ wpi_alloc_rpool(struct wpi_softc *sc)
 		SLIST_INSERT_HEAD(&ring->freelist, rbuf, next);
 	}
 
-	ring->nb_free_entries = WPI_RBUF_COUNT;
 	return 0;
 }
 
@@ -1471,7 +1467,7 @@ wpi_rx_intr(struct wpi_softc *sc, struct
 	struct ieee80211_frame *wh;
 	struct ieee80211_node *ni;
 	struct mbuf *m, *mnew;
-	int data_off;
+	int data_off, error;
 
 	bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
 	    BUS_DMASYNC_POSTREAD);
@@ -1505,68 +1501,56 @@ wpi_rx_intr(struct wpi_softc *sc, struct
 	/* Compute where are the useful datas */
 	data_off = (char*)(head + 1) - mtod(data->m, char*);
 			
-	/*
-	 * If the number of free entry is too low
-	 * just dup the data->m socket and reuse the same rbuf entry
-	 * Note that thi test is not protected by a mutex because the
-	 * only path that causes nb_free_entries to decrease is through
-	 * this interrupt routine, which is not re-entrent.
-	 * What may not be obvious is that the safe path is if that test
-	 * evaluates as true, so nb_free_entries can grow any time.
-	 */
-	if (sc->rxq.nb_free_entries <= WPI_RBUF_LOW_LIMIT) {
-	
-		/* Prepare the mbuf for the m_dup */
-		data->m->m_pkthdr.len = data->m->m_len = le16toh(head->len);
-		data->m->m_data = (char*) data->m->m_data + data_off;
-
-		m = m_dup(data->m,0,M_COPYALL,M_DONTWAIT);
-
-		/* Restore the m_data pointer for future use */
-		data->m->m_data = (char*) data->m->m_data - data_off;
-
-		if (m == NULL) {
-			ifp->if_ierrors++;
-			return;
-		}
-	} else {
-		int error;
+	MGETHDR(mnew, M_DONTWAIT, MT_DATA);
+	if (mnew == NULL) {
+		ifp->if_ierrors++;
+		return;
+	}
 
-		MGETHDR(mnew, M_DONTWAIT, MT_DATA);
-		if (mnew == NULL) {
-			ifp->if_ierrors++;
-			return;
-		}
+	rbuf = wpi_alloc_rbuf(sc);
+	if (rbuf == NULL) {
+		m_freem(mnew);
+		ifp->if_ierrors++;
+		return;
+	}
 
-		rbuf = wpi_alloc_rbuf(sc);
-		KASSERT(rbuf != NULL);
+	/* attach Rx buffer to mbuf */
+	MEXTADD(mnew, rbuf->vaddr, WPI_RBUF_SIZE, 0, wpi_free_rbuf,
+		rbuf);
+	mnew->m_flags |= M_EXT_RW;
 
-		/* attach Rx buffer to mbuf */
-		MEXTADD(mnew, rbuf->vaddr, WPI_RBUF_SIZE, 0, wpi_free_rbuf,
-			rbuf);
-		mnew->m_flags |= M_EXT_RW;
+	bus_dmamap_unload(sc->sc_dmat, data->map);
 
-		bus_dmamap_unload(sc->sc_dmat, data->map);
-		m = data->m;
-		data->m = mnew;
+	error = bus_dmamap_load(sc->sc_dmat, data->map,
+	    mtod(mnew, void *), WPI_RBUF_SIZE, NULL,
+	    BUS_DMA_NOWAIT | BUS_DMA_READ);
+	if (error) {
+		device_printf(sc->sc_dev,
+		    "couldn't load rx mbuf: %d\n", error);
+		m_freem(mnew);
+		ifp->if_ierrors++;
 
 		error = bus_dmamap_load(sc->sc_dmat, data->map,
 		    mtod(data->m, void *), WPI_RBUF_SIZE, NULL,
 		    BUS_DMA_NOWAIT | BUS_DMA_READ);
-		if (error) {
+		if (error)
 			panic("%s: bus_dmamap_load failed: %d\n",
 			    device_xname(sc->sc_dev), error);
-		}
+		return;
+	}
 
-		/* update Rx descriptor */
-		ring->desc[ring->cur] = htole32(rbuf->paddr);
-		bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
-		    ring->desc_dma.size,
-		    BUS_DMASYNC_PREWRITE);
+	/* new mbuf loaded successfully */
+	m = data->m;
+	data->m = mnew;
 
-		m->m_data = (char*)m->m_data + data_off;
-		m->m_pkthdr.len = m->m_len = le16toh(head->len);
-	}
+	/* update Rx descriptor */
+	ring->desc[ring->cur] = htole32(rbuf->paddr);
+	bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
+	    ring->desc_dma.size,
+	    BUS_DMASYNC_PREWRITE);
+
+	m->m_data = (char*)m->m_data + data_off;
+	m->m_pkthdr.len = m->m_len = le16toh(head->len);
 
 	/* finalize mbuf */
 	m->m_pkthdr.rcvif = ifp;
@@ -1698,10 +1682,11 @@ wpi_notif_intr(struct wpi_softc *sc)
 	hw = le32toh(sc->shared->next);
 	while (sc->rxq.cur != hw) {
 		struct wpi_rx_data *data = &sc->rxq.data[sc->rxq.cur];
-		struct wpi_rx_desc *desc = mtod(data->m, struct wpi_rx_desc *);
+		struct wpi_rx_desc *desc;
 
 		bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
 		    BUS_DMASYNC_POSTREAD);
+		desc = mtod(data->m, struct wpi_rx_desc *);
 
 		DPRINTFN(4, ("rx notification qid=%x idx=%d flags=%x type=%d "
 		    "len=%d\n", desc->qid, desc->idx, desc->flags,
@@ -2699,6 +2684,8 @@ wpi_setup_beacon(struct wpi_softc *sc, s
 	desc->segs[1].addr = htole32(data->map->dm_segs[0].ds_addr);
 	desc->segs[1].len  = htole32(data->map->dm_segs[0].ds_len);
 
+	bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
+	    ring->desc_dma.map->dm_mapsize, BUS_DMASYNC_PREWRITE);
 	bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
 	    BUS_DMASYNC_PREWRITE);
 
@@ -2932,6 +2919,8 @@ wpi_scan(struct wpi_softc *sc, uint16_t 
 	desc->segs[0].addr = htole32(data->map->dm_segs[0].ds_addr);
 	desc->segs[0].len  = htole32(data->map->dm_segs[0].ds_len);
 
+	bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
+	    ring->desc_dma.map->dm_mapsize, BUS_DMASYNC_PREWRITE);
 	bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
 	    BUS_DMASYNC_PREWRITE);
 

Index: src/sys/dev/pci/if_wpivar.h
diff -u src/sys/dev/pci/if_wpivar.h:1.16 src/sys/dev/pci/if_wpivar.h:1.17
--- src/sys/dev/pci/if_wpivar.h:1.16	Tue Aug  5 21:54:39 2014
+++ src/sys/dev/pci/if_wpivar.h	Thu Aug  7 02:28:52 2014
@@ -1,4 +1,4 @@
-/*  $NetBSD: if_wpivar.h,v 1.16 2014/08/05 21:54:39 jmcneill Exp $    */
+/*  $NetBSD: if_wpivar.h,v 1.17 2014/08/07 02:28:52 jmcneill Exp $    */
 
 /*-
  * Copyright (c) 2006
@@ -104,7 +104,6 @@ struct wpi_rx_ring {
 	struct wpi_rbuf		rbuf[WPI_RBUF_COUNT];
 	SLIST_HEAD(, wpi_rbuf)	freelist;
 	kmutex_t		freelist_mtx;
-	int			nb_free_entries;
 	int			cur;
 };
 

Reply via email to