Index: if_vmx.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_vmx.c,v retrieving revision 1.30 diff -u -p -r1.30 if_vmx.c --- if_vmx.c 24 Jun 2015 09:40:54 -0000 1.30 +++ if_vmx.c 13 Sep 2015 18:31:12 -0000 @@ -107,6 +107,7 @@ struct vmxnet3_softc { bus_space_handle_t sc_ioh0; bus_space_handle_t sc_ioh1; bus_dma_tag_t sc_dmat; + void *sc_ih; struct vmxnet3_txqueue sc_txq[NTXQUEUE]; struct vmxnet3_rxqueue sc_rxq[NRXQUEUE]; @@ -239,8 +240,8 @@ vmxnet3_attach(struct device *parent, st printf(": failed to map interrupt\n"); return; } - pci_intr_establish(pa->pa_pc, ih, IPL_NET, vmxnet3_intr, sc, - self->dv_xname); + sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET | IPL_MPSAFE, + vmxnet3_intr, sc, self->dv_xname); intrstr = pci_intr_string(pa->pa_pc, ih); if (intrstr) printf(": %s", intrstr); @@ -594,16 +595,19 @@ vmxnet3_intr(void *arg) if (READ_BAR1(sc, VMXNET3_BAR1_INTR) == 0) return 0; - if (sc->sc_ds->event) + + if (sc->sc_ds->event) { + KERNEL_LOCK(); vmxnet3_evintr(sc); -#ifdef VMXNET3_STAT - vmxstat.intr++; -#endif + KERNEL_UNLOCK(); + } + if (ifp->if_flags & IFF_RUNNING) { vmxnet3_rxintr(sc, &sc->sc_rxq[0]); vmxnet3_txintr(sc, &sc->sc_txq[0]); vmxnet3_enable_intr(sc, 0); } + return 1; } @@ -649,6 +653,7 @@ vmxnet3_txintr(struct vmxnet3_softc *sc, struct vmxnet3_comp_ring *comp_ring = &tq->comp_ring; struct vmxnet3_txcompdesc *txcd; struct ifnet *ifp = &sc->sc_arpcom.ac_if; + struct mbuf *m; u_int sop; for (;;) { @@ -667,18 +672,25 @@ vmxnet3_txintr(struct vmxnet3_softc *sc, sop = ring->next; if (ring->m[sop] == NULL) panic("%s: NULL ring->m[%u]", __func__, sop); - m_freem(ring->m[sop]); + + m = ring->m[sop]; ring->m[sop] = NULL; bus_dmamap_unload(sc->sc_dmat, ring->dmap[sop]); + m_freem(ring->m[sop]); + ring->next = (letoh32((txcd->txc_word0 >> VMXNET3_TXC_EOPIDX_S) & VMXNET3_TXC_EOPIDX_M) + 1) % NTXDESC; - - ifp->if_flags &= ~IFF_OACTIVE; } if (ring->head == ring->next) ifp->if_timer = 0; - vmxnet3_start(ifp); + + if (ISSET(ifp->if_flags, IFF_OACTIVE)) { + KERNEL_LOCK(); + CLR(ifp->if_flags, IFF_OACTIVE); + vmxnet3_start(ifp); + KERNEL_UNLOCK(); + } } void @@ -911,6 +923,8 @@ vmxnet3_stop(struct ifnet *ifp) WRITE_CMD(sc, VMXNET3_CMD_DISABLE); + intr_barrier(sc->sc_ih); + for (queue = 0; queue < NTXQUEUE; queue++) vmxnet3_txstop(sc, &sc->sc_txq[queue]); for (queue = 0; queue < NRXQUEUE; queue++) @@ -944,6 +958,11 @@ vmxnet3_init(struct vmxnet3_softc *sc) for (queue = 0; queue < NRXQUEUE; queue++) vmxnet3_rxinit(sc, &sc->sc_rxq[queue]); + for (queue = 0; queue < NRXQUEUE; queue++) { + WRITE_BAR0(sc, VMXNET3_BAR0_RXH1(queue), 0); + WRITE_BAR0(sc, VMXNET3_BAR0_RXH2(queue), 0); + } + WRITE_CMD(sc, VMXNET3_CMD_ENABLE); if (READ_BAR1(sc, VMXNET3_BAR1_CMD)) { printf("%s: failed to initialize\n", ifp->if_xname); @@ -951,11 +970,6 @@ vmxnet3_init(struct vmxnet3_softc *sc) return EIO; } - for (queue = 0; queue < NRXQUEUE; queue++) { - WRITE_BAR0(sc, VMXNET3_BAR0_RXH1(queue), 0); - WRITE_BAR0(sc, VMXNET3_BAR0_RXH2(queue), 0); - } - /* Program promiscuous mode and multicast filters. */ vmxnet3_iff(sc); @@ -1028,10 +1042,12 @@ vmxnet3_start(struct ifnet *ifp) struct vmxnet3_txring *ring = &tq->cmd_ring; struct mbuf *m; int n = 0; + int s; if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) return; + s = splnet(); for (;;) { IFQ_POLL(&ifp->if_snd, m); if (m == NULL) @@ -1057,12 +1073,7 @@ vmxnet3_start(struct ifnet *ifp) if (n > 0) WRITE_BAR0(sc, VMXNET3_BAR0_TXH(0), ring->head); -#ifdef VMXNET3_STAT - vmxstat.txhead = ring->head; - vmxstat.txdone = ring->next; - vmxstat.maxtxlen = - max(vmxstat.maxtxlen, (ring->head - ring->next) % NTXDESC); -#endif + splx(s); } int