summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2006-11-02 04:32:59 +0000
committerdlg <dlg@openbsd.org>2006-11-02 04:32:59 +0000
commit08e29dad2e90a8d51a9d9d67b4c65f1869b3864c (patch)
tree5f1c509bb23fb47d27f6fffdc4a0d0ea80d9a9a7
parentset the proper maximum queue length. (diff)
downloadwireguard-openbsd-08e29dad2e90a8d51a9d9d67b4c65f1869b3864c.tar.xz
wireguard-openbsd-08e29dad2e90a8d51a9d9d67b4c65f1869b3864c.zip
split the initialisation of the dma area up between the attach path and the
interface init path. the init path now does the allocation of the dmamaps for both tx and rx, and allocates the mbufs for the rx ring. the interface stop is now uncommented. it waits for the hardware to stop working, and cleans up the bits allocated in the init path. ifconfig vic0 up and ifconfig vic0 down both work now.
-rw-r--r--sys/dev/pci/if_vic.c173
1 files changed, 112 insertions, 61 deletions
diff --git a/sys/dev/pci/if_vic.c b/sys/dev/pci/if_vic.c
index 91bf199fde5..ddc0807e619 100644
--- a/sys/dev/pci/if_vic.c
+++ b/sys/dev/pci/if_vic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vic.c,v 1.22 2006/11/02 02:17:22 brad Exp $ */
+/* $OpenBSD: if_vic.c,v 1.23 2006/11/02 04:32:59 dlg Exp $ */
/*
* Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org>
@@ -141,6 +141,7 @@ int vic_map_pci(struct vic_softc *, struct pci_attach_args *);
int vic_query(struct vic_softc *);
int vic_alloc_data(struct vic_softc *);
int vic_init_data(struct vic_softc *sc);
+int vic_uninit_data(struct vic_softc *sc);
u_int32_t vic_read(struct vic_softc *, bus_size_t);
void vic_write(struct vic_softc *, bus_size_t, u_int32_t);
@@ -209,11 +210,6 @@ vic_attach(struct device *parent, struct device *self, void *aux)
return;
}
- if (vic_init_data(sc) != 0) {
- /* error printed by vic_alloc */
- return;
- }
-
bcopy(sc->sc_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
ifp = &sc->sc_ac.ac_if;
@@ -335,6 +331,11 @@ vic_query(struct vic_softc *sc)
int
vic_alloc_data(struct vic_softc *sc)
{
+ u_int8_t *kva;
+ u_int offset;
+ struct vic_rxdesc *rxd;
+ int i;
+
sc->sc_rxbuf = malloc(sizeof(struct vic_rxbuf) * sc->sc_nrxbuf,
M_NOWAIT, M_DEVBUF);
if (sc->sc_rxbuf == NULL) {
@@ -357,6 +358,46 @@ vic_alloc_data(struct vic_softc *sc)
printf("%s: unable to allocate dma region\n", DEVNAME(sc));
goto freetx;
}
+ kva = VIC_DMA_KVA(sc);
+
+ /* set up basic vic data */
+ sc->sc_data = VIC_DMA_KVA(sc);
+
+ sc->sc_data->vd_magic = VIC_MAGIC;
+ sc->sc_data->vd_length = sc->sc_dma_size;
+
+ offset = sizeof(struct vic_data);
+
+ /* set up the rx ring */
+ sc->sc_rxq = (struct vic_rxdesc *)&kva[offset];
+
+ sc->sc_data->vd_rx_offset = offset;
+ sc->sc_data->vd_rx_length = sc->sc_nrxbuf;
+
+ offset += sizeof(struct vic_rxdesc) * sc->sc_nrxbuf;
+
+ /* set up the dummy rx ring 2 with an unusable entry */
+ sc->sc_rxq2 = (struct vic_rxdesc *)&kva[offset];
+
+ sc->sc_data->vd_rx_offset2 = offset;
+ sc->sc_data->vd_rx_length2 = VIC_QUEUE2_SIZE;
+
+ for (i = 0; i < VIC_QUEUE2_SIZE; i++) {
+ rxd = &sc->sc_rxq2[i];
+
+ rxd->rx_physaddr = 0;
+ rxd->rx_buflength = 0;
+ rxd->rx_length = 0;
+ rxd->rx_owner = VIC_OWNER_DRIVER;
+
+ offset += sizeof(struct vic_rxdesc);
+ }
+
+ /* set up the tx ring */
+ sc->sc_txq = (struct vic_txdesc *)&kva[offset];
+
+ sc->sc_data->vd_tx_offset = offset;
+ sc->sc_data->vd_tx_length = sc->sc_ntxbuf;
return (0);
freetx:
@@ -370,29 +411,12 @@ err:
int
vic_init_data(struct vic_softc *sc)
{
- u_int8_t *kva = VIC_DMA_KVA(sc);
- u_int offset;
-
struct vic_rxbuf *rxb;
struct vic_rxdesc *rxd;
struct vic_txbuf *txb;
int i;
- /* set up basic vic data */
- sc->sc_data = VIC_DMA_KVA(sc);
-
- sc->sc_data->vd_magic = VIC_MAGIC;
- sc->sc_data->vd_length = sc->sc_dma_size;
-
- offset = sizeof(struct vic_data);
-
- /* set up the rx ring */
- sc->sc_rxq = (struct vic_rxdesc *)&kva[offset];
-
- sc->sc_data->vd_rx_offset = offset;
- sc->sc_data->vd_rx_length = sc->sc_nrxbuf;
-
for (i = 0; i < sc->sc_nrxbuf; i++) {
rxb = &sc->sc_rxbuf[i];
rxd = &sc->sc_rxq[i];
@@ -418,33 +442,8 @@ vic_init_data(struct vic_softc *sc)
rxd->rx_buflength = rxb->rxb_m->m_pkthdr.len; /* XXX? */
rxd->rx_length = 0;
rxd->rx_owner = VIC_OWNER_NIC;
-
- offset += sizeof(struct vic_rxdesc);
- }
-
- /* set up the dummy rx ring 2 with an unusable entry */
- sc->sc_rxq2 = (struct vic_rxdesc *)&kva[offset];
-
- sc->sc_data->vd_rx_offset2 = offset;
- sc->sc_data->vd_rx_length2 = VIC_QUEUE2_SIZE;
-
- for (i = 0; i < VIC_QUEUE2_SIZE; i++) {
- rxd = &sc->sc_rxq2[i];
-
- rxd->rx_physaddr = 0;
- rxd->rx_buflength = 0;
- rxd->rx_length = 0;
- rxd->rx_owner = VIC_OWNER_DRIVER;
-
- offset += sizeof(struct vic_rxdesc);
}
- /* set up the tx ring */
- sc->sc_txq = (struct vic_txdesc *)&kva[offset];
-
- sc->sc_data->vd_tx_offset = offset;
- sc->sc_data->vd_tx_length = sc->sc_ntxbuf;
-
for (i = 0; i < sc->sc_ntxbuf; i++) {
txb = &sc->sc_txbuf[i];
if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, VIC_SG_MAX,
@@ -477,6 +476,35 @@ freerxbs:
return (1);
}
+int
+vic_uninit_data(struct vic_softc *sc)
+{
+ struct vic_rxbuf *rxb;
+ struct vic_rxdesc *rxd;
+ struct vic_txbuf *txb;
+
+ int i;
+
+ for (i = 0; i < sc->sc_nrxbuf; i++) {
+ rxb = &sc->sc_rxbuf[i];
+ rxd = &sc->sc_rxq[i];
+
+ bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
+ rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
+ bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap);
+
+ m_freem(rxb->rxb_m);
+ rxb->rxb_m = NULL;
+ }
+
+ for (i = 0; i < sc->sc_ntxbuf; i++) {
+ txb = &sc->sc_txbuf[i];
+ bus_dmamap_destroy(sc->sc_dmat, txb->txb_dmamap);
+ }
+
+ return (0);
+}
void
vic_link_state(struct vic_softc *sc)
{
@@ -523,6 +551,9 @@ vic_rx_proc(struct vic_softc *sc)
struct mbuf *m;
int len, idx;
+ if ((ifp->if_flags & IFF_RUNNING) == 0)
+ return;
+
bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
@@ -719,6 +750,9 @@ vic_start(struct ifnet *ifp)
int i, idx;
int tx = 0;
+ if (!(ifp->if_flags & IFF_RUNNING))
+ return;
+
if (ifp->if_flags & IFF_OACTIVE)
return;
@@ -954,21 +988,32 @@ vic_init(struct ifnet *ifp)
struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
int s;
+ if (vic_init_data(sc) != 0)
+ return;
+
+ sc->sc_data->vd_tx_curidx = 0;
+ sc->sc_data->vd_tx_nextidx = 0;
+ sc->sc_data->vd_tx_stopped = sc->sc_data->vd_tx_queued = 0;
+
+ sc->sc_data->vd_rx_nextidx = 0;
+ sc->sc_data->vd_rx_nextidx2 = 0;
+
+ sc->sc_data->vd_rx_saved_nextidx = 0;
+ sc->sc_data->vd_rx_saved_nextidx2 = 0;
+ sc->sc_data->vd_tx_saved_nextidx = 0;
+
bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
s = splnet();
- vic_write(sc, VIC_DATA_ADDR, VIC_DMA_DVA(sc));
- vic_write(sc, VIC_DATA_LENGTH, sc->sc_dma_size);
if (ifp->if_flags & IFF_PROMISC)
vic_iff(sc, VIC_CMD_IFF_PROMISC);
else
vic_iff(sc, VIC_CMD_IFF_BROADCAST | VIC_CMD_IFF_MULTICAST);
- sc->sc_data->vd_tx_curidx = 0;
- sc->sc_data->vd_tx_nextidx = 0;
- sc->sc_data->vd_tx_stopped = sc->sc_data->vd_tx_queued = 0;
+ vic_write(sc, VIC_DATA_ADDR, VIC_DMA_DVA(sc));
+ vic_write(sc, VIC_DATA_LENGTH, sc->sc_dma_size);
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
@@ -981,27 +1026,33 @@ vic_init(struct ifnet *ifp)
void
vic_stop(struct ifnet *ifp)
{
-#if 0
struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
int s;
s = splnet();
- sc->sc_txtimeout = 0;
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
-#ifdef notyet
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ /* XXX wait for tx to complete */
+ while (sc->sc_txpending > 0) {
+ splx(s);
+ delay(1000);
+ s = splnet();
+ }
+
+ sc->sc_data->vd_tx_stopped = 1;
+
vic_write(sc, VIC_CMD, VIC_CMD_INTR_DISABLE);
-#endif
- vic_write(sc, VIC_DATA_ADDR, 0);
vic_iff(sc, 0);
+ vic_write(sc, VIC_DATA_ADDR, 0);
- sc->sc_data->vd_tx_stopped = 1;
- timeout_del(&sc->sc_timer);
+ vic_uninit_data(sc);
splx(s);
-#endif
}
struct mbuf *