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