PERFORCE change 136948 for review

Andrew Thompson thompsa at FreeBSD.org
Wed Mar 5 21:15:03 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=136948

Change 136948 by thompsa at thompsa_burger on 2008/03/05 21:14:42

	Merge Rx buffer handling improvements from iwn.
	
	Obtained from:	Sam Leffler via sam_vap branch

Affected files ...

.. //depot/projects/wifi/sys/dev/wpi/if_wpi.c#15 edit
.. //depot/projects/wifi/sys/dev/wpi/if_wpivar.h#6 edit

Differences ...

==== //depot/projects/wifi/sys/dev/wpi/if_wpi.c#15 (text+ko) ====

@@ -158,10 +158,6 @@
 static void	wpi_dma_map_addr(void *, bus_dma_segment_t *, int, int);
 static int	wpi_alloc_shared(struct wpi_softc *);
 static void	wpi_free_shared(struct wpi_softc *);
-static struct wpi_rbuf *wpi_alloc_rbuf(struct wpi_softc *);
-static void	wpi_free_rbuf(void *, void *);
-static int	wpi_alloc_rpool(struct wpi_softc *);
-static void	wpi_free_rpool(struct wpi_softc *);
 static int	wpi_alloc_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
 static void	wpi_reset_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
 static void	wpi_free_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
@@ -587,17 +583,6 @@
 		goto fail;
 	}
 
-	/*
-	 * Allocate the receive buffer pool. The recieve buffers are
-	 * WPI_RBUF_SIZE in length (3k) this is bigger than MCLBYTES
-	 * hence we can't simply use a cluster and used mapped dma memory
-	 * instead.
-	 */
-	if ((error = wpi_alloc_rpool(sc)) != 0) {
-	    device_printf(dev, "could not allocate Rx buffers\n");
-	    goto fail;
-	}
-
 	/* tx data queues  - 4 for QoS purposes */
 	for (ac = 0; ac < WME_NUM_AC; ac++) {
 		error = wpi_alloc_tx_ring(sc, &sc->txq[ac], WPI_TX_RING_COUNT, ac);
@@ -758,7 +743,6 @@
 
 		wpi_free_tx_ring(sc, &sc->cmdq);
 		wpi_free_rx_ring(sc, &sc->rxq);
-		wpi_free_rpool(sc);
 		wpi_free_shared(sc);
 	}
 
@@ -934,138 +918,79 @@
 	wpi_dma_contig_free(&sc->shared_dma);
 }
 
-struct wpi_rbuf *
-wpi_alloc_rbuf(struct wpi_softc *sc)
-{
-	struct wpi_rbuf *rbuf;
-
-	rbuf = SLIST_FIRST(&sc->rxq.freelist);
-	if (rbuf == NULL)
-		return NULL;
-	SLIST_REMOVE_HEAD(&sc->rxq.freelist, next);
-	return rbuf;
-}
-
-/*
- * This is called automatically by the network stack when the mbuf to which our
- * Rx buffer is attached is freed.
- */
-static void
-wpi_free_rbuf(void *buf, void *arg)
-{
-	struct wpi_rbuf *rbuf = arg;
-	struct wpi_softc *sc = rbuf->sc;
-	int waslocked;
-
-	/* XXX Horrible! use busdma? */
-	waslocked = WPI_LOCK_OWNED(sc);
-	if (!waslocked)
-		WPI_LOCK(sc);
-
-	/* put the buffer back in the free list */
-	SLIST_INSERT_HEAD(&sc->rxq.freelist, rbuf, next);
-
-	if (!waslocked)
-		WPI_UNLOCK(sc);
-}
-
-static int
-wpi_alloc_rpool(struct wpi_softc *sc)
-{
-	struct wpi_rx_ring *ring = &sc->rxq;
-	struct wpi_rbuf *rbuf;
-	int i, error;
-
-	/* allocate a big chunk of DMA'able memory.. */
-	error = wpi_dma_contig_alloc(sc, &ring->buf_dma, NULL,
-	    WPI_RBUF_COUNT * WPI_RBUF_SIZE, PAGE_SIZE, BUS_DMA_NOWAIT);
-	if (error != 0) {
-		device_printf(sc->sc_dev,
-		    "could not allocate Rx buffers DMA memory\n");
-		return error;
-	}
-
-	/* ..and split it into 3KB chunks */
-	SLIST_INIT(&ring->freelist);
-	for (i = 0; i < WPI_RBUF_COUNT; i++) {
-		rbuf = &ring->rbuf[i];
-
-		rbuf->sc = sc;	/* backpointer for callbacks */
-		rbuf->vaddr = ring->buf_dma.vaddr + i * WPI_RBUF_SIZE;
-		rbuf->paddr = ring->buf_dma.paddr + i * WPI_RBUF_SIZE;
-
-		SLIST_INSERT_HEAD(&ring->freelist, rbuf, next);
-	}
-	return 0;
-}
-
-static void
-wpi_free_rpool(struct wpi_softc *sc)
-{
-	wpi_dma_contig_free(&sc->rxq.buf_dma);
-}
-
 static int
 wpi_alloc_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
 {
 
-	struct wpi_rx_data *data;
-	struct wpi_rbuf *rbuf;
 	int i, error;
 
 	ring->cur = 0;
 
 	error = wpi_dma_contig_alloc(sc, &ring->desc_dma,
-		(void **)&ring->desc, WPI_RX_RING_COUNT * sizeof (uint32_t),
-		WPI_RING_DMA_ALIGN, BUS_DMA_NOWAIT);
+	    (void **)&ring->desc, WPI_RX_RING_COUNT * sizeof (uint32_t),
+	    WPI_RING_DMA_ALIGN, BUS_DMA_NOWAIT);
 
 	if (error != 0) {
-	    device_printf(sc->sc_dev,
-		"could not allocate rx ring DMA memory\n");
-	    goto fail;
+		device_printf(sc->sc_dev,
+		    "%s: could not allocate rx ring DMA memory, error %d\n",
+		    __func__, error);
+		goto fail;
 	}
 
+        error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 
+	    BUS_SPACE_MAXADDR_32BIT,
+            BUS_SPACE_MAXADDR, NULL, NULL, MJUMPAGESIZE, 1,
+            MJUMPAGESIZE, BUS_DMA_NOWAIT, NULL, NULL, &ring->data_dmat);
+        if (error != 0) {
+                device_printf(sc->sc_dev,
+		    "%s: bus_dma_tag_create_failed, error %d\n",
+		    __func__, error);
+                goto fail;
+        }
+
 	/*
-	 * Allocate Rx buffers.
+	 * Setup Rx buffers.
 	 */
 	for (i = 0; i < WPI_RX_RING_COUNT; i++) {
-		data = &ring->data[i];
+		struct wpi_rx_data *data = &ring->data[i];
+		struct mbuf *m;
+		bus_addr_t paddr;
 
-		data->m = m_gethdr(M_DONTWAIT, MT_DATA);
-		if (data->m == NULL) {
+		error = bus_dmamap_create(ring->data_dmat, 0, &data->map);
+		if (error != 0) {
 			device_printf(sc->sc_dev,
-			    "could not allocate rx mbuf\n");
-			error = ENOBUFS;
+			    "%s: bus_dmamap_create failed, error %d\n",
+			    __func__, error);
 			goto fail;
 		}
-
-		if ((rbuf = wpi_alloc_rbuf(sc)) == NULL) {
-			m_freem(data->m);
-			data->m = NULL;
+		m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
+		if (m == NULL) {
 			device_printf(sc->sc_dev,
-			    "could not allocate rx buffer\n");
-			error = ENOBUFS;
+			   "%s: could not allocate rx mbuf\n", __func__);
+			error = ENOMEM;
 			goto fail;
 		}
-
-		/* attach RxBuffer to mbuf */
-		MEXTADD(data->m, rbuf->vaddr, WPI_RBUF_SIZE,wpi_free_rbuf,
-		    rbuf->vaddr, rbuf, 0, EXT_NET_DRV);
-
-		if ((data->m->m_flags & M_EXT) == 0) {
-			m_freem(data->m);
-			data->m = NULL;
-			error = ENOBUFS;
+		/* map page */
+		error = bus_dmamap_load(ring->data_dmat, data->map,
+		    mtod(m, caddr_t), MJUMPAGESIZE,
+		    wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT);
+		if (error != 0 && error != EFBIG) {
+			device_printf(sc->sc_dev,
+			    "%s: bus_dmamap_load failed, error %d\n",
+			    __func__, error);
+			m_freem(m);
+			error = ENOMEM;	/* XXX unique code */
 			goto fail;
 		}
-		ring->desc[i] = htole32(rbuf->paddr);
+		bus_dmamap_sync(ring->data_dmat, data->map, 
+		    BUS_DMASYNC_PREWRITE);
+
+		data->m = m;
+		ring->desc[i] = htole32(paddr);
 	}
-
 	bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
 	    BUS_DMASYNC_PREWRITE);
-
 	return 0;
-
 fail:
 	wpi_free_rx_ring(sc, ring);
 	return error;
@@ -1089,7 +1014,7 @@
 	wpi_mem_unlock(sc);
 
 #ifdef WPI_DEBUG
-	if (ntries == 100 && wpi_debug > 0)
+	if (ntries == 100)
 		device_printf(sc->sc_dev, "timeout resetting Rx ring\n");
 #endif
 
@@ -1103,14 +1028,9 @@
 
 	wpi_dma_contig_free(&ring->desc_dma);
 
-	for (i = 0; i < WPI_RX_RING_COUNT; i++) {
-		if (ring->data[i].m != NULL) {
-			WPI_UNLOCK(sc);
+	for (i = 0; i < WPI_RX_RING_COUNT; i++)
+		if (ring->data[i].m != NULL)
 			m_freem(ring->data[i].m);
-			WPI_LOCK(sc);
-			ring->data[i].m = NULL;
-		}
-	}
 }
 
 static int
@@ -1180,7 +1100,8 @@
 
 	return 0;
 
-fail:	wpi_free_tx_ring(sc, ring);
+fail:
+	wpi_free_tx_ring(sc, ring);
 	return error;
 }
 
@@ -1199,10 +1120,9 @@
 		DELAY(10);
 	}
 #ifdef WPI_DEBUG
-	if (ntries == 100 && wpi_debug > 0) {
+	if (ntries == 100)
 		device_printf(sc->sc_dev, "timeout resetting Tx ring %d\n",
 		    ring->qid);
-	}
 #endif
 	wpi_mem_unlock(sc);
 
@@ -1571,9 +1491,10 @@
 	struct wpi_rx_stat *stat;
 	struct wpi_rx_head *head;
 	struct wpi_rx_tail *tail;
-	struct wpi_rbuf *rbuf;
 	struct ieee80211_node *ni;
 	struct mbuf *m, *mnew;
+	bus_addr_t paddr;
+	int error;
 
 	stat = (struct wpi_rx_stat *)(desc + 1);
 
@@ -1591,37 +1512,37 @@
 	    le16toh(head->len), (int8_t)stat->rssi, head->rate, head->chan,
 	    (uintmax_t)le64toh(tail->tstamp)));
 
+	/* XXX don't need mbuf, just dma buffer */
+	mnew = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
+	if (mnew == NULL) {
+		DPRINTFN(WPI_DEBUG_RX, ("%s: no mbuf to restock ring\n",
+		    __func__));
+		ic->ic_stats.is_rx_nobuf++;
+		ifp->if_ierrors++;
+		return;
+	}
+	error = bus_dmamap_load(ring->data_dmat, data->map,
+	    mtod(mnew, caddr_t), MJUMPAGESIZE,
+	    wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT);
+	if (error != 0 && error != EFBIG) {
+		device_printf(sc->sc_dev,
+		    "%s: bus_dmamap_load failed, error %d\n", __func__, error);
+		m_freem(mnew);
+		ic->ic_stats.is_rx_nobuf++;	/* XXX need stat */
+		ifp->if_ierrors++;
+		return;
+	}
+	bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE);
+
+	/* finalize mbuf and swap in new one */
 	m = data->m;
-
-	/* finalize mbuf */
 	m->m_pkthdr.rcvif = ifp;
 	m->m_data = (caddr_t)(head + 1);
 	m->m_pkthdr.len = m->m_len = le16toh(head->len);
 
-	if ((rbuf = SLIST_FIRST(&sc->rxq.freelist)) != NULL) {
-		mnew = m_gethdr(M_DONTWAIT,MT_DATA);
-		if (mnew == NULL) {
-			ifp->if_ierrors++;
-			return;
-		}
-
-		/* attach Rx buffer to mbuf */
-		MEXTADD(mnew, rbuf->vaddr, WPI_RBUF_SIZE, wpi_free_rbuf,
-		    rbuf->vaddr, rbuf, 0, EXT_NET_DRV);
-		SLIST_REMOVE_HEAD(&sc->rxq.freelist, next);
-		data->m = mnew;
-
-		/* update Rx descriptor */
-		ring->desc[ring->cur] = htole32(rbuf->paddr);
-	} else {
-		/* no free rbufs, copy frame */
-		m = m_dup(m, M_DONTWAIT);
-		if (m == NULL) {
-			/* no free mbufs either, drop frame */
-			ifp->if_ierrors++;
-			return;
-		}
-	}
+	data->m = mnew;
+	/* update Rx descriptor */
+	ring->desc[ring->cur] = htole32(paddr);
 
 	if (bpf_peers_present(sc->sc_drvbpf)) {
 		struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap;

==== //depot/projects/wifi/sys/dev/wpi/if_wpivar.h#6 (text+ko) ====

@@ -18,12 +18,6 @@
  */
 #include <net80211/ieee80211_amrr.h>
 
-/* DMA mapping */
-struct wpi_mapping {
-	int nsegs;
-	bus_dma_segment_t segs[WPI_MAX_SCATTER];
-};
-
 struct wpi_rx_radiotap_header {
 	struct ieee80211_radiotap_header wr_ihdr;
 	uint64_t	wr_tsft;
@@ -90,26 +84,16 @@
 
 #define WPI_RBUF_COUNT ( WPI_RX_RING_COUNT + 16 )
 
-struct wpi_softc;
-
-struct wpi_rbuf {
-	struct wpi_softc	*sc;
-	bus_addr_t		paddr;
-	caddr_t			vaddr;
-	SLIST_ENTRY(wpi_rbuf)	next;
-};
-
 struct wpi_rx_data {
-	struct mbuf	*m;
+	bus_dmamap_t		map;
+	struct mbuf		*m;
 };
 
 struct wpi_rx_ring {
 	struct wpi_dma_info	desc_dma;
-	struct wpi_dma_info	buf_dma;
 	uint32_t		*desc;
 	struct wpi_rx_data	data[WPI_RX_RING_COUNT];
-	struct wpi_rbuf		rbuf[WPI_RBUF_COUNT];
-	SLIST_HEAD(, wpi_rbuf)	freelist;
+	bus_dma_tag_t		data_dmat;
 	int			cur;
 };
 


More information about the p4-projects mailing list