diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2006-11-10 21:15:57 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2006-11-10 21:15:57 +0000 |
commit | ad1e175683d1623277294c81bb4c147ba30a6e82 (patch) | |
tree | d87fc3263841ad687b133775492467033c2d5166 /sys | |
parent | e7f3740f4f12ea46b396b24d250b2eb76780e1d2 (diff) |
Pre-allocate the TX DMA maps intead of creating and destroying a DMA map
per packet sent.
Tested by brad@, ckuethe@, Gabriel Kihlman <gk at stacken dot kth dot se>
and Tim Wiess <tim at nop dot cx>.
Tested with amd64/i386/sparc64.
ok damien@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_em.c | 105 | ||||
-rw-r--r-- | sys/dev/pci/if_em.h | 6 |
2 files changed, 69 insertions, 42 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index ff6b23b4731..0b8eeb6efcd 100644 --- a/sys/dev/pci/if_em.c +++ b/sys/dev/pci/if_em.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ -/* $OpenBSD: if_em.c,v 1.154 2006/11/07 21:05:56 brad Exp $ */ +/* $OpenBSD: if_em.c,v 1.155 2006/11/10 21:15:56 brad Exp $ */ /* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */ #include <dev/pci/if_em.h> @@ -918,16 +918,15 @@ em_encap(struct em_softc *sc, struct mbuf *m_head) { u_int32_t txd_upper; u_int32_t txd_lower, txd_used = 0, txd_saved = 0; - int i, j, error; + int i, j, error = 0; + bus_dmamap_t map; /* For 82544 Workaround */ DESC_ARRAY desc_array; u_int32_t array_elements; u_int32_t counter; - struct em_q q; - - struct em_buffer *tx_buffer = NULL; + struct em_buffer *tx_buffer; struct em_tx_desc *current_tx_desc = NULL; /* @@ -945,25 +944,19 @@ em_encap(struct em_softc *sc, struct mbuf *m_head) /* * Map the packet for DMA. */ - if (bus_dmamap_create(sc->txtag, MAX_JUMBO_FRAME_SIZE, - EM_MAX_SCATTER, MAX_JUMBO_FRAME_SIZE, 0, - BUS_DMA_NOWAIT, &q.map)) { - sc->no_tx_map_avail++; - return (ENOMEM); - } - error = bus_dmamap_load_mbuf(sc->txtag, q.map, + tx_buffer = &sc->tx_buffer_area[sc->next_avail_tx_desc]; + error = bus_dmamap_load_mbuf(sc->txtag, tx_buffer->map, m_head, BUS_DMA_NOWAIT); + map = tx_buffer->map; if (error != 0) { sc->no_tx_dma_setup++; - bus_dmamap_destroy(sc->txtag, q.map); return (error); } - EM_KASSERT(q.map->dm_nsegs!= 0, ("em_encap: empty packet")); + EM_KASSERT(map->dm_nsegs!= 0, ("em_encap: empty packet")); - if (q.map->dm_nsegs > sc->num_tx_desc_avail) { + if (map->dm_nsegs > sc->num_tx_desc_avail) { sc->no_tx_desc_avail2++; - bus_dmamap_destroy(sc->txtag, q.map); - return (ENOBUFS); + goto fail; } #ifdef EM_CSUM_OFFLOAD @@ -980,22 +973,21 @@ em_encap(struct em_softc *sc, struct mbuf *m_head) txd_saved = i; txd_used = 0; } - for (j = 0; j < q.map->dm_nsegs; j++) { + for (j = 0; j < map->dm_nsegs; j++) { /* If sc is 82544 and on PCI-X bus */ if (sc->pcix_82544) { /* * Check the Address and Length combination and * split the data accordingly */ - array_elements = em_fill_descriptors(q.map->dm_segs[j].ds_addr, - q.map->dm_segs[j].ds_len, + array_elements = em_fill_descriptors(map->dm_segs[j].ds_addr, + map->dm_segs[j].ds_len, &desc_array); for (counter = 0; counter < array_elements; counter++) { if (txd_used == sc->num_tx_desc_avail) { sc->next_avail_tx_desc = txd_saved; sc->no_tx_desc_avail2++; - bus_dmamap_destroy(sc->txtag, q.map); - return (ENOBUFS); + goto fail; } tx_buffer = &sc->tx_buffer_area[i]; current_tx_desc = &sc->tx_desc_base[i]; @@ -1015,9 +1007,9 @@ em_encap(struct em_softc *sc, struct mbuf *m_head) tx_buffer = &sc->tx_buffer_area[i]; current_tx_desc = &sc->tx_desc_base[i]; - current_tx_desc->buffer_addr = htole64(q.map->dm_segs[j].ds_addr); + current_tx_desc->buffer_addr = htole64(map->dm_segs[j].ds_addr); current_tx_desc->lower.data = htole32( - sc->txd_cmd | txd_lower | q.map->dm_segs[j].ds_len); + sc->txd_cmd | txd_lower | map->dm_segs[j].ds_len); current_tx_desc->upper.data = htole32(txd_upper); if (++i == sc->num_tx_desc) @@ -1031,11 +1023,10 @@ em_encap(struct em_softc *sc, struct mbuf *m_head) if (sc->pcix_82544) sc->num_tx_desc_avail -= txd_used; else - sc->num_tx_desc_avail -= q.map->dm_nsegs; + sc->num_tx_desc_avail -= map->dm_nsegs; tx_buffer->m_head = m_head; - tx_buffer->map = q.map; - bus_dmamap_sync(sc->txtag, q.map, 0, q.map->dm_mapsize, + bus_dmamap_sync(sc->txtag, map, 0, map->dm_mapsize, BUS_DMASYNC_PREWRITE); /* @@ -1060,6 +1051,10 @@ em_encap(struct em_softc *sc, struct mbuf *m_head) } return (0); + +fail: + bus_dmamap_unload(sc->txtag, map); + return (ENOBUFS); } /********************************************************************* @@ -1820,14 +1815,30 @@ em_allocate_transmit_structures(struct em_softc *sc) int em_setup_transmit_structures(struct em_softc *sc) { - sc->txtag = sc->osdep.em_pa.pa_dmat; + struct em_buffer *tx_buffer; + int error, i; - if (em_allocate_transmit_structures(sc)) - return (ENOMEM); + if ((error = em_allocate_transmit_structures(sc)) != 0) + goto fail; bzero((void *) sc->tx_desc_base, (sizeof(struct em_tx_desc)) * sc->num_tx_desc); + sc->txtag = sc->osdep.em_pa.pa_dmat; + + tx_buffer = sc->tx_buffer_area; + for (i = 0; i < sc->num_tx_desc; i++) { + error = bus_dmamap_create(sc->txtag, MAX_JUMBO_FRAME_SIZE, + EM_MAX_SCATTER, MAX_JUMBO_FRAME_SIZE, 0, + BUS_DMA_NOWAIT, &tx_buffer->map); + if (error != 0) { + printf("%s: Unable to create TX DMA map\n", + sc->sc_dv.dv_xname); + goto fail; + } + tx_buffer++; + } + sc->next_avail_tx_desc = 0; sc->oldest_used_tx_desc = 0; @@ -1836,8 +1847,14 @@ em_setup_transmit_structures(struct em_softc *sc) /* Set checksum context */ sc->active_checksum_context = OFFLOAD_NONE; + bus_dmamap_sync(sc->txdma.dma_tag, sc->txdma.dma_map, 0, + sc->txdma.dma_size, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); return (0); + +fail: + em_free_transmit_structures(sc); + return (error); } /********************************************************************* @@ -1930,12 +1947,23 @@ em_free_transmit_structures(struct em_softc *sc) if (sc->tx_buffer_area != NULL) { tx_buffer = sc->tx_buffer_area; for (i = 0; i < sc->num_tx_desc; i++, tx_buffer++) { + if (tx_buffer->map != NULL && + tx_buffer->map->dm_nsegs > 0) { + bus_dmamap_sync(sc->txtag, tx_buffer->map, + 0, tx_buffer->map->dm_mapsize, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->txtag, + tx_buffer->map); + } if (tx_buffer->m_head != NULL) { - bus_dmamap_unload(sc->txtag, tx_buffer->map); - bus_dmamap_destroy(sc->txtag, tx_buffer->map); m_freem(tx_buffer->m_head); + tx_buffer->m_head = NULL; + } + if (tx_buffer->map != NULL) { + bus_dmamap_destroy(sc->txtag, + tx_buffer->map); + tx_buffer->map = NULL; } - tx_buffer->m_head = NULL; } } if (sc->tx_buffer_area != NULL) { @@ -2057,11 +2085,14 @@ em_txeof(struct em_softc *sc) tx_desc->upper.data = 0; num_avail++; - if (tx_buffer->m_head) { + if (tx_buffer->m_head != NULL) { ifp->if_opackets++; - bus_dmamap_unload(sc->txtag, tx_buffer->map); - bus_dmamap_destroy(sc->txtag, tx_buffer->map); - + if (tx_buffer->map->dm_nsegs > 0) { + bus_dmamap_sync(sc->txtag, tx_buffer->map, + 0, tx_buffer->map->dm_mapsize, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->txtag, tx_buffer->map); + } m_freem(tx_buffer->m_head); tx_buffer->m_head = NULL; } diff --git a/sys/dev/pci/if_em.h b/sys/dev/pci/if_em.h index b3df0df9d18..0cfc2242014 100644 --- a/sys/dev/pci/if_em.h +++ b/sys/dev/pci/if_em.h @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* $FreeBSD: if_em.h,v 1.26 2004/09/01 23:22:41 pdeuskar Exp $ */ -/* $OpenBSD: if_em.h,v 1.30 2006/11/06 03:52:37 brad Exp $ */ +/* $OpenBSD: if_em.h,v 1.31 2006/11/10 21:15:56 brad Exp $ */ #ifndef _EM_H_DEFINED_ #define _EM_H_DEFINED_ @@ -266,10 +266,6 @@ struct em_buffer { bus_dmamap_t map; /* bus_dma map for packet */ }; -struct em_q { - bus_dmamap_t map; /* bus_dma map for packet */ -}; - /* * Bus dma allocation structure used by * em_dma_malloc and em_dma_free. |