diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2007-08-23 13:52:30 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2007-08-23 13:52:30 +0000 |
commit | ee144c2db77d1112352984c97da9757fd132faca (patch) | |
tree | aac66a492d27a8f4047fb0895da0d55d4883ef2b /sys/dev/pci/if_nxe.c | |
parent | 30ef79932d1153019099efab10f01f7ac644abe0 (diff) |
implement the completion half of the tx path. the driver keeps track of
mbufs we've put on the hardware with the nxe_pkt struct. this struct
contains a unique id for each pkt which is used the hardwares tx descriptor
so we could identify which pkts its finished transmitting. turns out the
hardware doesnt return ids though, it tells us which slots in the tx ring
its up to. so now i stash the slot a pkt went into in the pkt_id field.
Diffstat (limited to 'sys/dev/pci/if_nxe.c')
-rw-r--r-- | sys/dev/pci/if_nxe.c | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/sys/dev/pci/if_nxe.c b/sys/dev/pci/if_nxe.c index 0b1edbf7c12..2ba4f24858b 100644 --- a/sys/dev/pci/if_nxe.c +++ b/sys/dev/pci/if_nxe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_nxe.c,v 1.45 2007/08/23 13:31:39 dlg Exp $ */ +/* $OpenBSD: if_nxe.c,v 1.46 2007/08/23 13:52:29 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -650,7 +650,7 @@ struct nxe_dmamem { #define NXE_DMA_KVA(_ndm) ((void *)(_ndm)->ndm_kva) struct nxe_pkt { - u_int16_t pkt_id; + int pkt_id; bus_dmamap_t pkt_dmap; struct mbuf *pkt_m; TAILQ_ENTRY(nxe_pkt) pkt_link; @@ -712,6 +712,7 @@ struct nxe_softc { struct nxe_dmamem *sc_ctx; u_int32_t *sc_cmd_consumer; + u_int32_t sc_cmd_consumer_cur; struct nxe_ring *sc_cmd_ring; struct nxe_ring *sc_rx_rings[NXE_NRING]; @@ -760,6 +761,7 @@ void nxe_link_state(struct nxe_softc *); /* interface operations */ int nxe_ioctl(struct ifnet *, u_long, caddr_t); void nxe_start(struct ifnet *); +int nxe_complete(struct nxe_softc *); void nxe_watchdog(struct ifnet *); void nxe_up(struct nxe_softc *); @@ -1101,6 +1103,7 @@ nxe_up(struct nxe_softc *sc) ctx->ctx_id = htole32(sc->sc_function); sc->sc_cmd_consumer = &dmamem->cmd_consumer; + sc->sc_cmd_consumer_cur = 0; /* allocate the cmd/tx ring */ sc->sc_cmd_ring = nxe_ring_alloc(sc, @@ -1287,7 +1290,7 @@ nxe_start(struct ifnet *ifp) IFQ_IS_EMPTY(&ifp->if_snd)) return; - if (nxe_ring_writeable(nr, 0 /* XXX */) < NXE_TXD_DESCS) { + if (nxe_ring_writeable(nr, sc->sc_cmd_consumer_cur) < NXE_TXD_DESCS) { SET(ifp->if_flags, IFF_OACTIVE); return; } @@ -1327,7 +1330,6 @@ nxe_start(struct ifnet *ifp) txd->tx_flags = htole16(NXE_TXD_F_OPCODE_TX); txd->tx_nbufs = dmap->dm_nsegs; txd->tx_length = htole16(dmap->dm_mapsize); - txd->tx_id = pkt->pkt_id; txd->tx_port = sc->sc_port; segs = dmap->dm_segs; @@ -1356,6 +1358,8 @@ nxe_start(struct ifnet *ifp) nsegs -= NXE_TXD_SEGS; segs += NXE_TXD_SEGS; + pkt->pkt_id = nr->nr_slot; + txd = nxe_ring_next(sc, nr); bzero(txd, sizeof(struct nxe_tx_desc)); } while (nsegs > 0); @@ -1370,6 +1374,52 @@ nxe_start(struct ifnet *ifp) nxe_crb_write(sc, NXE_1_SW_CMD_PRODUCER(sc->sc_function), nr->nr_slot); } +int +nxe_complete(struct nxe_softc *sc) +{ + struct nxe_pkt *pkt; + int new_cons, cur_cons; + int rv = 0; + + bus_dmamap_sync(sc->sc_dmat, NXE_DMA_MAP(sc->sc_ctx), + 0, NXE_DMA_LEN(sc->sc_ctx), + BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); + new_cons = letoh32(*sc->sc_cmd_consumer); + bus_dmamap_sync(sc->sc_dmat, NXE_DMA_MAP(sc->sc_ctx), + 0, NXE_DMA_LEN(sc->sc_ctx), + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + cur_cons = sc->sc_cmd_consumer_cur; + pkt = nxe_pkt_used(sc->sc_tx_pkts); + + while (pkt != NULL && cur_cons != new_cons) { + if (pkt->pkt_id == cur_cons) { + bus_dmamap_sync(sc->sc_dmat, pkt->pkt_dmap, + 0, pkt->pkt_dmap->dm_mapsize, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->sc_dmat, pkt->pkt_dmap); + + m_freem(pkt->pkt_m); + + nxe_pkt_put(sc->sc_tx_pkts, pkt); + + pkt = nxe_pkt_used(sc->sc_tx_pkts); + } + + cur_cons++; + cur_cons %= sc->sc_cmd_ring->nr_nentries; + + rv = 1; + } + + if (rv == 1) { + sc->sc_cmd_consumer_cur = cur_cons; + CLR(sc->sc_ac.ac_if.if_flags, IFF_OACTIVE); + } + + return (rv); +} + struct mbuf * nxe_coalesce_m(struct mbuf *m) { |