summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_em.c117
-rw-r--r--sys/dev/pci/if_em.h3
2 files changed, 73 insertions, 47 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index d029794e30d..e08be39ead7 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.147 2006/09/17 17:51:01 brad Exp $ */
+/* $OpenBSD: if_em.c,v 1.148 2006/09/17 20:26:14 brad Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -159,7 +159,7 @@ void em_set_promisc(struct em_softc *);
void em_set_multi(struct em_softc *);
void em_print_hw_stats(struct em_softc *);
void em_update_link_status(struct em_softc *);
-int em_get_buf(int, struct em_softc *, struct mbuf *);
+int em_get_buf(struct em_softc *, int);
int em_encap(struct em_softc *, struct mbuf *);
void em_smartspeed(struct em_softc *);
int em_82547_fifo_workaround(struct em_softc *, int);
@@ -2090,55 +2090,59 @@ em_txeof(struct em_softc *sc)
*
**********************************************************************/
int
-em_get_buf(int i, struct em_softc *sc, struct mbuf *nmp)
+em_get_buf(struct em_softc *sc, int i)
{
- struct mbuf *mp = nmp;
+ struct mbuf *m;
+ bus_dmamap_t map;
struct em_buffer *rx_buffer;
struct ifnet *ifp;
int error;
ifp = &sc->interface_data.ac_if;
- if (mp == NULL) {
- MGETHDR(mp, M_DONTWAIT, MT_DATA);
- if (mp == NULL) {
- sc->mbuf_alloc_failed++;
- return (ENOBUFS);
- }
- MCLGET(mp, M_DONTWAIT);
- if ((mp->m_flags & M_EXT) == 0) {
- m_freem(mp);
- sc->mbuf_cluster_failed++;
- return (ENOBUFS);
- }
- mp->m_len = mp->m_pkthdr.len = MCLBYTES;
- } else {
- mp->m_len = mp->m_pkthdr.len = MCLBYTES;
- mp->m_data = mp->m_ext.ext_buf;
- mp->m_next = NULL;
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+ sc->mbuf_alloc_failed++;
+ return (ENOBUFS);
+ }
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
+ sc->mbuf_cluster_failed++;
+ return (ENOBUFS);
}
+ m->m_len = m->m_pkthdr.len = MCLBYTES;
if (sc->hw.max_frame_size <= (MCLBYTES - ETHER_ALIGN))
- m_adj(mp, ETHER_ALIGN);
-
- rx_buffer = &sc->rx_buffer_area[i];
+ m_adj(m, ETHER_ALIGN);
/*
* Using memory from the mbuf cluster pool, invoke the
* bus_dma machinery to arrange the memory mapping.
*/
- error = bus_dmamap_load(sc->rxtag, rx_buffer->map,
- mtod(mp, void *), mp->m_len, NULL, 0);
+ error = bus_dmamap_load(sc->rxtag, sc->rx_sparemap,
+ mtod(m, void *), m->m_len, NULL, BUS_DMA_NOWAIT);
if (error) {
- m_free(mp);
+ m_free(m);
return (error);
}
- rx_buffer->m_head = mp;
- sc->rx_desc_base[i].buffer_addr = htole64(rx_buffer->map->dm_segs[0].ds_addr);
+
+ rx_buffer = &sc->rx_buffer_area[i];
+ if (rx_buffer->m_head != NULL)
+ bus_dmamap_unload(sc->rxtag, rx_buffer->map);
+
+ map = rx_buffer->map;
+ rx_buffer->map = sc->rx_sparemap;
+ sc->rx_sparemap = map;
+
bus_dmamap_sync(sc->rxtag, rx_buffer->map, 0,
rx_buffer->map->dm_mapsize,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ rx_buffer->m_head = m;
+
+ sc->rx_desc_base[i].buffer_addr = htole64(rx_buffer->map->dm_segs[0].ds_addr);
+
return (0);
}
@@ -2170,6 +2174,15 @@ em_allocate_receive_structures(struct em_softc *sc)
sc->rxtag = sc->osdep.em_pa.pa_dmat;
+ error = bus_dmamap_create(sc->rxtag, MCLBYTES, 1, MCLBYTES,
+ 0, BUS_DMA_NOWAIT, &sc->rx_sparemap);
+ if (error != 0) {
+ printf("%s: em_allocate_receive_structures: "
+ "bus_dmamap_create failed; error %u\n",
+ sc->sc_dv.dv_xname, error);
+ goto fail;
+ }
+
rx_buffer = sc->rx_buffer_area;
for (i = 0; i < sc->num_rx_desc; i++, rx_buffer++) {
error = bus_dmamap_create(sc->rxtag, MCLBYTES, 1,
@@ -2184,7 +2197,7 @@ em_allocate_receive_structures(struct em_softc *sc)
}
for (i = 0; i < sc->num_rx_desc; i++) {
- error = em_get_buf(i, sc, NULL);
+ error = em_get_buf(sc, i);
if (error != 0) {
sc->rx_buffer_area[i].m_head = NULL;
sc->rx_desc_base[i].buffer_addr = 0;
@@ -2318,6 +2331,10 @@ em_free_receive_structures(struct em_softc *sc)
INIT_DEBUGOUT("free_receive_structures: begin");
+ if (sc->rx_sparemap) {
+ bus_dmamap_destroy(sc->rxtag, sc->rx_sparemap);
+ sc->rx_sparemap = NULL;
+ }
if (sc->rx_buffer_area != NULL) {
rx_buffer = sc->rx_buffer_area;
for (i = 0; i < sc->num_rx_desc; i++, rx_buffer++) {
@@ -2360,6 +2377,7 @@ em_rxeof(struct em_softc *sc, int count)
/* Pointer to the receive descriptor being examined. */
struct em_rx_desc *current_desc;
+ u_int8_t status;
ifp = &sc->interface_data.ac_if;
i = sc->next_rx_desc_to_check;
@@ -2376,15 +2394,19 @@ em_rxeof(struct em_softc *sc, int count)
struct mbuf *m = NULL;
mp = sc->rx_buffer_area[i].m_head;
+ /*
+ * Can't defer bus_dmamap_sync(9) because TBI_ACCEPT
+ * needs to access the last received byte in the mbuf.
+ */
bus_dmamap_sync(sc->rxtag, sc->rx_buffer_area[i].map,
0, sc->rx_buffer_area[i].map->dm_mapsize,
BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(sc->rxtag, sc->rx_buffer_area[i].map);
accept_frame = 1;
prev_len_adj = 0;
desc_len = letoh16(current_desc->length);
- if (current_desc->status & E1000_RXD_STAT_EOP) {
+ status = current_desc->status;
+ if (status & E1000_RXD_STAT_EOP) {
count--;
eop = 1;
if (desc_len < ETHER_CRC_LEN) {
@@ -2405,8 +2427,7 @@ em_rxeof(struct em_softc *sc, int count)
pkt_len += sc->fmp->m_pkthdr.len;
last_byte = *(mtod(mp, caddr_t) + desc_len - 1);
- if (TBI_ACCEPT(&sc->hw, current_desc->status,
- current_desc->errors,
+ if (TBI_ACCEPT(&sc->hw, status, current_desc->errors,
pkt_len, last_byte)) {
em_tbi_adjust_stats(&sc->hw,
&sc->stats,
@@ -2419,14 +2440,9 @@ em_rxeof(struct em_softc *sc, int count)
}
if (accept_frame) {
- if (em_get_buf(i, sc, NULL) == ENOBUFS) {
+ if (em_get_buf(sc, i) != 0) {
sc->dropped_pkts++;
- em_get_buf(i, sc, mp);
- if (sc->fmp != NULL)
- m_freem(sc->fmp);
- sc->fmp = NULL;
- sc->lmp = NULL;
- break;
+ goto discard;
}
/* Assign correct length to the current fragment */
@@ -2512,11 +2528,20 @@ em_rxeof(struct em_softc *sc, int count)
}
} else {
sc->dropped_pkts++;
- em_get_buf(i, sc, mp);
- if (sc->fmp != NULL)
- m_freem(sc->fmp);
- sc->fmp = NULL;
- sc->lmp = NULL;
+discard:
+ /* Reuse loaded DMA map and just update mbuf chain */
+ mp = sc->rx_buffer_area[i].m_head;
+ mp->m_len = mp->m_pkthdr.len = MCLBYTES;
+ mp->m_data = mp->m_ext.ext_buf;
+ mp->m_next = NULL;
+ if (sc->hw.max_frame_size <= (MCLBYTES - ETHER_ALIGN))
+ m_adj(mp, ETHER_ALIGN);
+ if (sc->fmp != NULL) {
+ m_freem(sc->fmp);
+ sc->fmp = NULL;
+ sc->lmp = NULL;
+ }
+ m = NULL;
}
/* Zero out the receive descriptors status. */
diff --git a/sys/dev/pci/if_em.h b/sys/dev/pci/if_em.h
index 8a7f970cbb3..1fc3feff912 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.28 2006/09/17 17:51:01 brad Exp $ */
+/* $OpenBSD: if_em.h,v 1.29 2006/09/17 20:26:14 brad Exp $ */
#ifndef _EM_H_DEFINED_
#define _EM_H_DEFINED_
@@ -347,6 +347,7 @@ struct em_softc {
u_int32_t txd_cmd;
struct em_buffer *tx_buffer_area;
bus_dma_tag_t txtag; /* dma tag for tx */
+ bus_dmamap_t rx_sparemap;
/*
* Receive definitions