From owner-p4-projects@FreeBSD.ORG Wed Mar 5 21:15:02 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 5A7A71065674; Wed, 5 Mar 2008 21:15:02 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 19C9F106566B for ; Wed, 5 Mar 2008 21:15:02 +0000 (UTC) (envelope-from thompsa@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 0E8458FC1C for ; Wed, 5 Mar 2008 21:15:02 +0000 (UTC) (envelope-from thompsa@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m25LF1NK001410 for ; Wed, 5 Mar 2008 21:15:01 GMT (envelope-from thompsa@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m25LF1xl001408 for perforce@freebsd.org; Wed, 5 Mar 2008 21:15:01 GMT (envelope-from thompsa@freebsd.org) Date: Wed, 5 Mar 2008 21:15:01 GMT Message-Id: <200803052115.m25LF1xl001408@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to thompsa@freebsd.org using -f From: Andrew Thompson To: Perforce Change Reviews Cc: Subject: PERFORCE change 136948 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Mar 2008 21:15:03 -0000 http://perforce.freebsd.org/chv.cgi?CH=136948 Change 136948 by thompsa@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 -/* 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; };