aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ti/if_ti.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ti/if_ti.c')
-rw-r--r--sys/dev/ti/if_ti.c407
1 files changed, 321 insertions, 86 deletions
diff --git a/sys/dev/ti/if_ti.c b/sys/dev/ti/if_ti.c
index a4e924a80019..a21191b910c9 100644
--- a/sys/dev/ti/if_ti.c
+++ b/sys/dev/ti/if_ti.c
@@ -202,6 +202,8 @@ static void ti_rxeof(struct ti_softc *);
static void ti_stats_update(struct ti_softc *);
static int ti_encap(struct ti_softc *, struct mbuf *, u_int32_t *);
+static void ti_encap_cb(void *arg, bus_dma_segment_t *segs, int nseg,
+ bus_size_t mapsize, int error);
static void ti_intr(void *);
static void ti_start(struct ifnet *);
@@ -231,8 +233,10 @@ static void ti_loadfw(struct ti_softc *);
static void ti_cmd(struct ti_softc *, struct ti_cmd_desc *);
static void ti_cmd_ext(struct ti_softc *, struct ti_cmd_desc *, caddr_t, int);
static void ti_handle_events(struct ti_softc *);
-#ifdef TI_PRIVATE_JUMBOS
+static int ti_alloc_dmamaps(struct ti_softc *);
+static void ti_free_dmamaps(struct ti_softc *);
static int ti_alloc_jumbo_mem(struct ti_softc *);
+#ifdef TI_PRIVATE_JUMBOS
static void *ti_jalloc(struct ti_softc *);
static void ti_jfree(void *, void *);
#endif /* TI_PRIVATE_JUMBOS */
@@ -951,6 +955,58 @@ ti_handle_events(sc)
}
}
+static int
+ti_alloc_dmamaps(struct ti_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < TI_TX_RING_CNT; i++) {
+ if (bus_dmamap_create(sc->ti_mbuftx_dmat, 0,
+ &sc->ti_cdata.ti_tx_maps[i]))
+ return (ENOBUFS);
+ }
+ for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
+ if (bus_dmamap_create(sc->ti_mbufrx_dmat, 0,
+ &sc->ti_cdata.ti_rx_std_maps[i]))
+ return (ENOBUFS);
+ }
+
+ for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
+ if (bus_dmamap_create(sc->ti_jumbo_dmat, 0,
+ &sc->ti_cdata.ti_rx_jumbo_maps[i]))
+ return (ENOBUFS);
+ }
+ for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
+ if (bus_dmamap_create(sc->ti_mbufrx_dmat, 0,
+ &sc->ti_cdata.ti_rx_mini_maps[i]))
+ return (ENOBUFS);
+ }
+
+ return (0);
+}
+
+static void
+ti_free_dmamaps(struct ti_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < TI_TX_RING_CNT; i++)
+ bus_dmamap_destroy(sc->ti_mbuftx_dmat,
+ sc->ti_cdata.ti_tx_maps[i]);
+
+ for (i = 0; i < TI_STD_RX_RING_CNT; i++)
+ bus_dmamap_destroy(sc->ti_mbufrx_dmat,
+ sc->ti_cdata.ti_rx_std_maps[i]);
+
+ for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++)
+ bus_dmamap_destroy(sc->ti_jumbo_dmat,
+ sc->ti_cdata.ti_rx_jumbo_maps[i]);
+
+ for (i = 0; i < TI_MINI_RX_RING_CNT; i++)
+ bus_dmamap_destroy(sc->ti_mbufrx_dmat,
+ sc->ti_cdata.ti_rx_mini_maps[i]);
+}
+
#ifdef TI_PRIVATE_JUMBOS
/*
@@ -984,10 +1040,14 @@ ti_alloc_jumbo_mem(sc)
register int i;
struct ti_jpool_entry *entry;
- /* Grab a big chunk o' storage. */
+ /*
+ * Grab a big chunk o' storage. Since we are chopping this pool up
+ * into ~9k chunks, there doesn't appear to be a need to use page
+ * alignment.
+ */
if (bus_dma_tag_create(sc->ti_parent_dmat, /* parent */
- PAGE_SIZE, 0, /* algnmnt, boundary */
- BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ 1, 0, /* algnmnt, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
TI_JMEM, /* maxsize */
@@ -996,14 +1056,14 @@ ti_alloc_jumbo_mem(sc)
0, /* flags */
NULL, NULL, /* lockfunc, lockarg */
&sc->ti_jumbo_dmat) != 0) {
- device_printf(dev, "Failed to allocate jumbo dmat\n");
+ device_printf(sc->ti_dev, "Failed to allocate jumbo dmat\n");
return (ENOBUFS);
}
if (bus_dmamem_alloc(sc->ti_jumbo_dmat,
(void**)&sc->ti_cdata.ti_jumbo_buf,
BUS_DMA_NOWAIT, &sc->ti_jumbo_dmamap) != 0) {
- device_printf(dev, "Failed to allocate jumbo memory\n");
+ device_printf(sc->ti_dev, "Failed to allocate jumbo memory\n");
return (ENOBUFS);
}
@@ -1021,7 +1081,7 @@ ti_alloc_jumbo_mem(sc)
entry = malloc(sizeof(struct ti_jpool_entry),
M_DEVBUF, M_NOWAIT);
if (entry == NULL) {
- device_printf(dev, "no memory for jumbo "
+ device_printf(sc->ti_dev, "no memory for jumbo "
"buffer queue!\n");
return (ENOBUFS);
}
@@ -1085,6 +1145,35 @@ ti_jfree(buf, args)
SLIST_INSERT_HEAD(&sc->ti_jfree_listhead, entry, jpool_entries);
}
+#else
+
+static int
+ti_alloc_jumbo_mem(sc)
+ struct ti_softc *sc;
+{
+
+ /*
+ * The VM system will take care of providing aligned pages. Alignment
+ * is set to 1 here so that busdma resources won't be wasted.
+ */
+ if (bus_dma_tag_create(sc->ti_parent_dmat, /* parent */
+ 1, 0, /* algnmnt, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ PAGE_SIZE * 4 /*XXX*/, /* maxsize */
+ 4, /* nsegments */
+ PAGE_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->ti_jumbo_dmat) != 0) {
+ device_printf(sc->ti_dev, "Failed to allocate jumbo dmat\n");
+ return (ENOBUFS);
+ }
+
+ return (0);
+}
+
#endif /* TI_PRIVATE_JUMBOS */
/*
@@ -1096,9 +1185,13 @@ ti_newbuf_std(sc, i, m)
int i;
struct mbuf *m;
{
+ bus_dmamap_t map;
+ bus_dma_segment_t segs;
struct mbuf *m_new = NULL;
struct ti_rx_desc *r;
+ int nsegs;
+ nsegs = 0;
if (m == NULL) {
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
if (m_new == NULL)
@@ -1119,14 +1212,21 @@ ti_newbuf_std(sc, i, m)
m_adj(m_new, ETHER_ALIGN);
sc->ti_cdata.ti_rx_std_chain[i] = m_new;
r = &sc->ti_rdata->ti_rx_std_ring[i];
- TI_HOSTADDR(r->ti_addr) = vtophys(mtod(m_new, caddr_t));
+ map = sc->ti_cdata.ti_rx_std_maps[i];
+ if (bus_dmamap_load_mbuf_sg(sc->ti_mbufrx_dmat, map, m_new, &segs,
+ &nsegs, 0))
+ return (ENOBUFS);
+ if (nsegs != 1)
+ return (ENOBUFS);
+ ti_hostaddr64(&r->ti_addr, segs.ds_addr);
+ r->ti_len = segs.ds_len;
r->ti_type = TI_BDTYPE_RECV_BD;
r->ti_flags = 0;
if (sc->ti_ifp->if_hwassist)
r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
- r->ti_len = m_new->m_len;
r->ti_idx = i;
+ bus_dmamap_sync(sc->ti_mbufrx_dmat, map, BUS_DMASYNC_PREREAD);
return (0);
}
@@ -1140,9 +1240,13 @@ ti_newbuf_mini(sc, i, m)
int i;
struct mbuf *m;
{
+ bus_dma_segment_t segs;
+ bus_dmamap_t map;
struct mbuf *m_new = NULL;
struct ti_rx_desc *r;
+ int nsegs;
+ nsegs = 0;
if (m == NULL) {
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
if (m_new == NULL) {
@@ -1158,14 +1262,21 @@ ti_newbuf_mini(sc, i, m)
m_adj(m_new, ETHER_ALIGN);
r = &sc->ti_rdata->ti_rx_mini_ring[i];
sc->ti_cdata.ti_rx_mini_chain[i] = m_new;
- TI_HOSTADDR(r->ti_addr) = vtophys(mtod(m_new, caddr_t));
+ map = sc->ti_cdata.ti_rx_mini_maps[i];
+ if (bus_dmamap_load_mbuf_sg(sc->ti_mbufrx_dmat, map, m_new, &segs,
+ &nsegs, 0))
+ return (ENOBUFS);
+ if (nsegs != 1)
+ return (ENOBUFS);
+ ti_hostaddr64(&r->ti_addr, segs.ds_addr);
+ r->ti_len = segs.ds_len;
r->ti_type = TI_BDTYPE_RECV_BD;
r->ti_flags = TI_BDFLAG_MINI_RING;
if (sc->ti_ifp->if_hwassist)
r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
- r->ti_len = m_new->m_len;
r->ti_idx = i;
+ bus_dmamap_sync(sc->ti_mbufrx_dmat, map, BUS_DMASYNC_PREREAD);
return (0);
}
@@ -1181,8 +1292,11 @@ ti_newbuf_jumbo(sc, i, m)
int i;
struct mbuf *m;
{
+ bus_dmamap_t map;
struct mbuf *m_new = NULL;
struct ti_rx_desc *r;
+ int nsegs;
+ bus_dma_segment_t segs;
if (m == NULL) {
caddr_t *buf = NULL;
@@ -1217,14 +1331,21 @@ ti_newbuf_jumbo(sc, i, m)
/* Set up the descriptor. */
r = &sc->ti_rdata->ti_rx_jumbo_ring[i];
sc->ti_cdata.ti_rx_jumbo_chain[i] = m_new;
- TI_HOSTADDR(r->ti_addr) = vtophys(mtod(m_new, caddr_t));
+ map = sc->ti_cdata.ti_rx_jumbo_maps[i];
+ if (bus_dmamap_load_mbuf_sg(sc->ti_jumbo_dmat, map, m_new, &segs,
+ &nsegs, 0))
+ return (ENOBUFS);
+ if (nsegs != 1)
+ return (ENOBUFS);
+ ti_hostaddr64(&r->ti_addr, segs.ds_addr);
+ r->ti_len = segs.ds_len;
r->ti_type = TI_BDTYPE_RECV_JUMBO_BD;
r->ti_flags = TI_BDFLAG_JUMBO_RING;
if (sc->ti_ifp->if_hwassist)
r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
- r->ti_len = m_new->m_len;
r->ti_idx = i;
+ bus_dmamap_sync(sc->ti_jumbo_dmat, map, BUS_DMASYNC_PREREAD);
return (0);
}
@@ -1253,6 +1374,7 @@ ti_newbuf_jumbo(sc, idx, m_old)
int idx;
struct mbuf *m_old;
{
+ bus_dmamap_t map;
struct mbuf *cur, *m_new = NULL;
struct mbuf *m[3] = {NULL, NULL, NULL};
struct ti_rx_desc_ext *r;
@@ -1261,6 +1383,8 @@ ti_newbuf_jumbo(sc, idx, m_old)
/* 1 extra buf to make nobufs easy*/
struct sf_buf *sf[3] = {NULL, NULL, NULL};
int i;
+ bus_dma_segment_t segs[4];
+ int nsegs;
if (m_old != NULL) {
m_new = m_old;
@@ -1340,17 +1464,23 @@ ti_newbuf_jumbo(sc, idx, m_old)
/* Set up the descriptor. */
r = &sc->ti_rdata->ti_rx_jumbo_ring[idx];
sc->ti_cdata.ti_rx_jumbo_chain[idx] = m_new;
- TI_HOSTADDR(r->ti_addr0) = vtophys(mtod(m_new, caddr_t));
+ map = sc->ti_cdata.ti_rx_jumbo_maps[i];
+ if (bus_dmamap_load_mbuf_sg(sc->ti_jumbo_dmat, map, m_new, segs,
+ &nsegs, 0))
+ return (ENOBUFS);
+ if ((nsegs < 1) || (nsegs > 4))
+ return (ENOBUFS);
+ ti_hostaddr64(&r->ti_addr0, segs[0].ds_addr);
r->ti_len0 = m_new->m_len;
- TI_HOSTADDR(r->ti_addr1) = vtophys(mtod(m[0], caddr_t));
+ ti_hostaddr64(&r->ti_addr1, segs[1].ds_addr);
r->ti_len1 = PAGE_SIZE;
- TI_HOSTADDR(r->ti_addr2) = vtophys(mtod(m[1], caddr_t));
+ ti_hostaddr64(&r->ti_addr2, segs[2].ds_addr);
r->ti_len2 = m[1]->m_ext.ext_size; /* could be PAGE_SIZE or MCLBYTES */
if (PAGE_SIZE == 4096) {
- TI_HOSTADDR(r->ti_addr3) = vtophys(mtod(m[2], caddr_t));
+ ti_hostaddr64(&r->ti_addr3, segs[3].ds_addr);
r->ti_len3 = MCLBYTES;
} else {
r->ti_len3 = 0;
@@ -1364,6 +1494,7 @@ ti_newbuf_jumbo(sc, idx, m_old)
r->ti_idx = idx;
+ bus_dmamap_sync(sc->ti_jumbo_dmat, map, BUS_DMASYNC_PREREAD);
return (0);
nobufs:
@@ -2075,6 +2206,7 @@ ti_attach(dev)
sc = device_get_softc(dev);
sc->ti_unit = device_get_unit(dev);
+ sc->ti_dev = dev;
mtx_init(&sc->ti_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
@@ -2201,13 +2333,49 @@ ti_attach(dev)
bzero(sc->ti_rdata, sizeof(struct ti_ring_data));
/* Try to allocate memory for jumbo buffers. */
-#ifdef TI_PRIVATE_JUMBOS
if (ti_alloc_jumbo_mem(sc)) {
device_printf(dev, "jumbo buffer allocation failed\n");
error = ENXIO;
goto fail;
}
-#endif
+
+ if (bus_dma_tag_create(sc->ti_parent_dmat, /* parent */
+ 1, 0, /* algnmnt, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MCLBYTES * TI_MAXTXSEGS,/* maxsize */
+ TI_MAXTXSEGS, /* nsegments */
+ MCLBYTES, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->ti_mbuftx_dmat) != 0) {
+ device_printf(dev, "Failed to allocate rdata dmat\n");
+ error = ENOMEM;
+ goto fail;
+ }
+
+ if (bus_dma_tag_create(sc->ti_parent_dmat, /* parent */
+ 1, 0, /* algnmnt, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MCLBYTES, /* maxsize */
+ 1, /* nsegments */
+ MCLBYTES, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->ti_mbufrx_dmat) != 0) {
+ device_printf(dev, "Failed to allocate rdata dmat\n");
+ error = ENOMEM;
+ goto fail;
+ }
+
+ if (ti_alloc_dmamaps(sc)) {
+ device_printf(dev, "dma map creation failed\n");
+ error = ENXIO;
+ goto fail;
+ }
/*
* We really need a better way to tell a 1000baseTX card
@@ -2337,6 +2505,7 @@ ti_detach(dev)
ti_stop(sc);
ether_ifdetach(ifp);
bus_generic_detach(dev);
+ ti_free_dmamaps(sc);
}
ifmedia_removeall(&sc->ifmedia);
@@ -2344,9 +2513,13 @@ ti_detach(dev)
if (sc->ti_cdata.ti_jumbo_buf)
bus_dmamem_free(sc->ti_jumbo_dmat, sc->ti_cdata.ti_jumbo_buf,
sc->ti_jumbo_dmamap);
+#endif
if (sc->ti_jumbo_dmat)
bus_dma_tag_destroy(sc->ti_jumbo_dmat);
-#endif
+ if (sc->ti_mbuftx_dmat)
+ bus_dma_tag_destroy(sc->ti_mbuftx_dmat);
+ if (sc->ti_mbufrx_dmat)
+ bus_dma_tag_destroy(sc->ti_mbufrx_dmat);
if (sc->ti_rdata)
bus_dmamem_free(sc->ti_rdata_dmat, sc->ti_rdata,
sc->ti_rdata_dmamap);
@@ -2443,6 +2616,7 @@ static void
ti_rxeof(sc)
struct ti_softc *sc;
{
+ bus_dmamap_t map;
struct ifnet *ifp;
struct ti_cmd_desc cmd;
@@ -2472,6 +2646,10 @@ ti_rxeof(sc)
TI_INC(sc->ti_jumbo, TI_JUMBO_RX_RING_CNT);
m = sc->ti_cdata.ti_rx_jumbo_chain[rxidx];
sc->ti_cdata.ti_rx_jumbo_chain[rxidx] = NULL;
+ map = sc->ti_cdata.ti_rx_jumbo_maps[rxidx];
+ bus_dmamap_sync(sc->ti_jumbo_dmat, map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->ti_jumbo_dmat, map);
if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
ifp->if_ierrors++;
ti_newbuf_jumbo(sc, sc->ti_jumbo, m);
@@ -2497,6 +2675,10 @@ ti_rxeof(sc)
TI_INC(sc->ti_mini, TI_MINI_RX_RING_CNT);
m = sc->ti_cdata.ti_rx_mini_chain[rxidx];
sc->ti_cdata.ti_rx_mini_chain[rxidx] = NULL;
+ map = sc->ti_cdata.ti_rx_mini_maps[rxidx];
+ bus_dmamap_sync(sc->ti_mbufrx_dmat, map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->ti_mbufrx_dmat, map);
if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
ifp->if_ierrors++;
ti_newbuf_mini(sc, sc->ti_mini, m);
@@ -2512,6 +2694,10 @@ ti_rxeof(sc)
TI_INC(sc->ti_std, TI_STD_RX_RING_CNT);
m = sc->ti_cdata.ti_rx_std_chain[rxidx];
sc->ti_cdata.ti_rx_std_chain[rxidx] = NULL;
+ map = sc->ti_cdata.ti_rx_std_maps[rxidx];
+ bus_dmamap_sync(sc->ti_mbufrx_dmat, map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->ti_mbufrx_dmat, map);
if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
ifp->if_ierrors++;
ti_newbuf_std(sc, sc->ti_std, m);
@@ -2564,6 +2750,7 @@ ti_txeof(sc)
{
struct ti_tx_desc *cur_tx = NULL;
struct ifnet *ifp;
+ bus_dmamap_t map;
ifp = sc->ti_ifp;
@@ -2596,6 +2783,10 @@ ti_txeof(sc)
if (sc->ti_cdata.ti_tx_chain[idx] != NULL) {
m_freem(sc->ti_cdata.ti_tx_chain[idx]);
sc->ti_cdata.ti_tx_chain[idx] = NULL;
+ map = sc->ti_cdata.ti_tx_maps[idx];
+ bus_dmamap_sync(sc->ti_mbuftx_dmat, map,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->ti_mbuftx_dmat, map);
}
sc->ti_txcnt--;
TI_INC(sc->ti_tx_saved_considx, TI_TX_RING_CNT);
@@ -2665,6 +2856,90 @@ ti_stats_update(sc)
ifp->if_collisions;
}
+struct ti_dmamap_arg {
+ struct ti_softc *sc;
+ struct m_tag *mtag;
+ struct mbuf *m_head;
+ u_int16_t csum_flags;
+ int idx;
+};
+
+static void
+ti_encap_cb(arg, segs, nseg, mapsize, error)
+ void *arg;
+ bus_dma_segment_t *segs;
+ int nseg;
+ bus_size_t mapsize;
+ int error;
+{
+ struct ti_softc *sc;
+ struct ti_dmamap_arg *ctx;
+ struct ti_tx_desc *f = NULL;
+ struct m_tag *mtag;
+ u_int32_t frag, cur, cnt = 0;
+ u_int16_t csum_flags;
+
+ if (error)
+ return;
+
+ ctx = (struct ti_dmamap_arg *)arg;
+ sc = ctx->sc;
+ cur = frag = ctx->idx;
+ mtag = ctx->mtag;
+ csum_flags = ctx->csum_flags;
+
+ /*
+ * Start packing the mbufs in this chain into
+ * the fragment pointers. Stop when we run out
+ * of fragments or hit the end of the mbuf chain.
+ */
+ while (nseg-- > 0) {
+ if (sc->ti_hwrev == TI_HWREV_TIGON) {
+ if (frag > 383)
+ CSR_WRITE_4(sc, TI_WINBASE,
+ TI_TX_RING_BASE + 6144);
+ else if (frag > 255)
+ CSR_WRITE_4(sc, TI_WINBASE,
+ TI_TX_RING_BASE + 4096);
+ else if (frag > 127)
+ CSR_WRITE_4(sc, TI_WINBASE,
+ TI_TX_RING_BASE + 2048);
+ else
+ CSR_WRITE_4(sc, TI_WINBASE,
+ TI_TX_RING_BASE);
+ f = &sc->ti_rdata->ti_tx_ring_nic[frag % 128];
+ } else
+ f = &sc->ti_rdata->ti_tx_ring[frag];
+ if (sc->ti_cdata.ti_tx_chain[frag] != NULL)
+ break;
+ ti_hostaddr64(&f->ti_addr, segs[cnt].ds_addr);
+ f->ti_len = segs[cnt].ds_len;
+ f->ti_flags = csum_flags;
+
+ if (mtag != NULL) {
+ f->ti_flags |= TI_BDFLAG_VLAN_TAG;
+ f->ti_vlan_tag = VLAN_TAG_VALUE(mtag) & 0xfff;
+ } else {
+ f->ti_vlan_tag = 0;
+ }
+
+ cur = frag;
+ TI_INC(frag, TI_TX_RING_CNT);
+ cnt++;
+ }
+
+ if (sc->ti_hwrev == TI_HWREV_TIGON)
+ sc->ti_rdata->ti_tx_ring_nic[cur % 128].ti_flags |=
+ TI_BDFLAG_END;
+ else
+ sc->ti_rdata->ti_tx_ring[cur].ti_flags |= TI_BDFLAG_END;
+ sc->ti_cdata.ti_tx_chain[cur] = ctx->m_head;
+ sc->ti_txcnt += cnt;
+
+ ctx->idx = frag;
+
+}
+
/*
* Encapsulate an mbuf chain in the tx ring by coupling the mbuf data
* pointers to descriptors.
@@ -2675,14 +2950,13 @@ ti_encap(sc, m_head, txidx)
struct mbuf *m_head;
u_int32_t *txidx;
{
- struct ti_tx_desc *f = NULL;
- struct mbuf *m;
- u_int32_t frag, cur, cnt = 0;
+ bus_dmamap_t map;
+ struct ti_dmamap_arg ctx;
+ u_int32_t frag, cnt;;
u_int16_t csum_flags = 0;
- struct m_tag *mtag;
+ int error;
- m = m_head;
- cur = frag = *txidx;
+ frag = *txidx;
if (m_head->m_pkthdr.csum_flags) {
if (m_head->m_pkthdr.csum_flags & CSUM_IP)
@@ -2695,72 +2969,33 @@ ti_encap(sc, m_head, txidx)
csum_flags |= TI_BDFLAG_IP_FRAG;
}
- mtag = VLAN_OUTPUT_TAG(sc->ti_ifp, m);
-
- /*
- * Start packing the mbufs in this chain into
- * the fragment pointers. Stop when we run out
- * of fragments or hit the end of the mbuf chain.
- */
- for (m = m_head; m != NULL; m = m->m_next) {
- if (m->m_len != 0) {
- if (sc->ti_hwrev == TI_HWREV_TIGON) {
- if (frag > 383)
- CSR_WRITE_4(sc, TI_WINBASE,
- TI_TX_RING_BASE + 6144);
- else if (frag > 255)
- CSR_WRITE_4(sc, TI_WINBASE,
- TI_TX_RING_BASE + 4096);
- else if (frag > 127)
- CSR_WRITE_4(sc, TI_WINBASE,
- TI_TX_RING_BASE + 2048);
- else
- CSR_WRITE_4(sc, TI_WINBASE,
- TI_TX_RING_BASE);
- f = &sc->ti_rdata->ti_tx_ring_nic[frag % 128];
- } else
- f = &sc->ti_rdata->ti_tx_ring[frag];
- if (sc->ti_cdata.ti_tx_chain[frag] != NULL)
- break;
- TI_HOSTADDR(f->ti_addr) = vtophys(mtod(m, vm_offset_t));
- f->ti_len = m->m_len;
- f->ti_flags = csum_flags;
-
- if (mtag != NULL) {
- f->ti_flags |= TI_BDFLAG_VLAN_TAG;
- f->ti_vlan_tag = VLAN_TAG_VALUE(mtag) & 0xfff;
- } else {
- f->ti_vlan_tag = 0;
- }
+ ctx.sc = sc;
+ ctx.idx = frag;
+ ctx.csum_flags = csum_flags;
+ ctx.mtag = VLAN_OUTPUT_TAG(sc->ti_ifp, m_head);
+ ctx.m_head = m_head;
- /*
- * Sanity check: avoid coming within 16 descriptors
- * of the end of the ring.
- */
- if ((TI_TX_RING_CNT - (sc->ti_txcnt + cnt)) < 16)
- return (ENOBUFS);
- cur = frag;
- TI_INC(frag, TI_TX_RING_CNT);
- cnt++;
- }
- }
-
- if (m != NULL)
+ map = sc->ti_cdata.ti_tx_maps[frag];
+ error = bus_dmamap_load_mbuf(sc->ti_mbuftx_dmat, map, m_head,
+ ti_encap_cb, &ctx, 0);
+ if (error)
return (ENOBUFS);
- if (frag == sc->ti_tx_saved_considx)
- return (ENOBUFS);
+ cnt = ctx.idx - frag;
+ frag = ctx.idx;
- if (sc->ti_hwrev == TI_HWREV_TIGON)
- sc->ti_rdata->ti_tx_ring_nic[cur % 128].ti_flags |=
- TI_BDFLAG_END;
- else
- sc->ti_rdata->ti_tx_ring[cur].ti_flags |= TI_BDFLAG_END;
- sc->ti_cdata.ti_tx_chain[cur] = m_head;
- sc->ti_txcnt += cnt;
+ /*
+ * Sanity check: avoid coming within 16 descriptors
+ * of the end of the ring.
+ */
+ if (((TI_TX_RING_CNT - (sc->ti_txcnt + cnt)) < 16) ||
+ (frag == sc->ti_tx_saved_considx)) {
+ bus_dmamap_unload(sc->ti_mbuftx_dmat, map);
+ return (ENOBUFS);
+ }
+ bus_dmamap_sync(sc->ti_mbuftx_dmat, map, BUS_DMASYNC_PREWRITE);
*txidx = frag;
-
return (0);
}