summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_nxe.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2007-08-23 13:52:30 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2007-08-23 13:52:30 +0000
commitee144c2db77d1112352984c97da9757fd132faca (patch)
treeaac66a492d27a8f4047fb0895da0d55d4883ef2b /sys/dev/pci/if_nxe.c
parent30ef79932d1153019099efab10f01f7ac644abe0 (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.c58
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)
{