diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2007-08-15 06:45:16 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2007-08-15 06:45:16 +0000 |
commit | d517d1ae6bcca202f23b9404413225fa7ae433c6 (patch) | |
tree | 2e9c07f7a5c4c84abe9193eb596536e1c89a0fdc /sys/dev/pci | |
parent | c07eae7e3b9bbb2a7fa4cf632fff162bbc264c0a (diff) |
when the interface is brought up allocate all the things that are needed
for the chip to work with, eg, the context region, the cmd consumer, the
cmd/tx ring, the status ring, and the 3 rx rings.
free it all when we bring the chip down.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_nxe.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/sys/dev/pci/if_nxe.c b/sys/dev/pci/if_nxe.c index adb761a498a..5d1ebe54879 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.33 2007/08/15 06:14:00 dlg Exp $ */ +/* $OpenBSD: if_nxe.c,v 1.34 2007/08/15 06:45:15 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -689,6 +689,13 @@ struct nxe_softc { /* allocations for the hw */ struct nxe_dmamem *sc_dummy_dma; + struct nxe_dmamem *sc_ctx; + u_int32_t *sc_cmd_consumer; + + struct nxe_ring *sc_cmd_ring; + struct nxe_ring *sc_rx_rings[NXE_NRING]; + struct nxe_ring *sc_status_ring; + /* monitoring */ struct timeout sc_tick; struct ksensor sc_sensor; @@ -1010,9 +1017,22 @@ err: void nxe_up(struct nxe_softc *sc) { + struct ifnet *ifp = &sc->sc_ac.ac_if; + static const u_int rx_ring_sizes[] = { 16384, 1024, 128 }; + struct { + struct nxe_ctx ctx; + u_int32_t cmd_consumer; + } __packed *dmamem; + struct nxe_ctx *ctx; + struct nxe_ctx_ring *ring; + struct nxe_ring *nr; + u_int64_t dva; + int i; + if (nxe_up_fw(sc) != 0) return; + /* allocate pkt lists */ sc->sc_tx_pkts = nxe_pkt_alloc(sc, 128, NXE_TXD_MAX_SEGS); if (sc->sc_tx_pkts == NULL) return; @@ -1020,9 +1040,69 @@ nxe_up(struct nxe_softc *sc) if (sc->sc_rx_pkts == NULL) goto free_tx_pkts; + /* allocate the context memory and the consumer field */ + sc->sc_ctx = nxe_dmamem_alloc(sc, sizeof(*dmamem), PAGE_SIZE); + if (sc->sc_ctx == NULL) + goto free_rx_pkts; + + dmamem = NXE_DMA_KVA(sc->sc_ctx); + dva = NXE_DMA_DVA(sc->sc_ctx); + + ctx = &dmamem->ctx; + ctx->ctx_cmd_consumer_addr = htole64(dva + sizeof(dmamem->ctx)); + ctx->ctx_id = htole32(sc->sc_function); + + sc->sc_cmd_consumer = &dmamem->cmd_consumer; + + /* allocate the cmd/tx ring */ + sc->sc_cmd_ring = nxe_ring_alloc(sc, + sizeof(struct nxe_tx_desc), 1024 /* XXX */); + if (sc->sc_cmd_ring == NULL) + goto free_ctx; + + ctx->ctx_cmd_ring.r_addr = + htole64(NXE_DMA_DVA(sc->sc_cmd_ring->nr_dmamem)); + ctx->ctx_cmd_ring.r_size = htole64(sc->sc_cmd_ring->nr_nentries); + + /* allocate the status ring */ + sc->sc_status_ring = nxe_ring_alloc(sc, + sizeof(struct nxe_status_desc), 16384 /* XXX */); + if (sc->sc_status_ring == NULL) + goto free_cmd_ring; + + ctx->ctx_status_ring_addr = + htole64(NXE_DMA_DVA(sc->sc_status_ring->nr_dmamem)); + ctx->ctx_status_ring_size = htole64(sc->sc_status_ring->nr_nentries); + + /* allocate the rx rings */ + for (i = 0; i < NXE_NRING; i++) { + ring = &ctx->ctx_rx_rings[i]; + nr = nxe_ring_alloc(sc, sizeof(struct nxe_rx_desc), + rx_ring_sizes[i]); + if (nr == NULL) + goto free_rx_rings; + + ring->r_addr = htole64(NXE_DMA_DVA(nr->nr_dmamem)); + ring->r_size = htole32(nr->nr_nentries); + + sc->sc_rx_rings[i] = nr; + } + + SET(ifp->if_flags, IFF_RUNNING); return; +free_rx_rings: + while (i > 0) + nxe_ring_free(sc, sc->sc_rx_rings[--i]); + + nxe_ring_free(sc, sc->sc_status_ring); +free_cmd_ring: + nxe_ring_free(sc, sc->sc_cmd_ring); +free_ctx: + nxe_dmamem_free(sc, sc->sc_ctx); +free_rx_pkts: + nxe_pkt_free(sc, sc->sc_rx_pkts); free_tx_pkts: nxe_pkt_free(sc, sc->sc_tx_pkts); } @@ -1061,9 +1141,15 @@ void nxe_down(struct nxe_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; + int i; CLR(ifp->if_flags, IFF_RUNNING | IFF_OACTIVE | IFF_ALLMULTI); + for (i = 0; i < NXE_NRING; i++) + nxe_ring_free(sc, sc->sc_rx_rings[i]); + nxe_ring_free(sc, sc->sc_status_ring); + nxe_ring_free(sc, sc->sc_cmd_ring); + nxe_dmamem_free(sc, sc->sc_ctx); nxe_pkt_free(sc, sc->sc_rx_pkts); nxe_pkt_free(sc, sc->sc_tx_pkts); } |