diff options
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_vic.c | 264 |
1 files changed, 133 insertions, 131 deletions
diff --git a/sys/dev/pci/if_vic.c b/sys/dev/pci/if_vic.c index 2f3ccc9e8e0..df25dc0bb53 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.58 2008/11/24 13:10:16 dlg Exp $ */ +/* $OpenBSD: if_vic.c,v 1.59 2008/11/24 16:13:47 dlg Exp $ */ /* * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org> @@ -185,13 +185,15 @@ struct vic_stats { u_int32_t vs_rx_underrun; } __packed; +#define VIC_NRXRINGS 2 + struct vic_data { u_int32_t vd_magic; - u_int32_t vd_rx_length; - u_int32_t vd_rx_nextidx; - u_int32_t vd_rx_length2; - u_int32_t vd_rx_nextidx2; + struct { + u_int32_t length; + u_int32_t nextidx; + } vd_rx[VIC_NRXRINGS]; u_int32_t vd_irq; u_int32_t vd_iff; @@ -210,13 +212,11 @@ struct vic_data { u_int32_t vd_reserved2[6]; - u_int32_t vd_rx_saved_nextidx; - u_int32_t vd_rx_saved_nextidx2; + u_int32_t vd_rx_saved_nextidx[VIC_NRXRINGS]; u_int32_t vd_tx_saved_nextidx; u_int32_t vd_length; - u_int32_t vd_rx_offset; - u_int32_t vd_rx_offset2; + u_int32_t vd_rx_offset[VIC_NRXRINGS]; u_int32_t vd_tx_offset; u_int32_t vd_debug; u_int32_t vd_tx_physaddr; @@ -290,13 +290,13 @@ struct vic_softc { struct vic_data *sc_data; - struct vic_rxbuf *sc_rxbuf; - struct vic_rxdesc *sc_rxq; - int sc_rxq_end; - int sc_rxq_len; - struct vic_rxdesc *sc_rxq2; - int sc_rxq_end2; - int sc_rxq_len2; + struct { + struct vic_rxbuf *bufs; + struct vic_rxdesc *slots; + int end; + int len; + u_int pktlen; + } sc_rxq[VIC_NRXRINGS]; struct vic_txbuf *sc_txbuf; struct vic_txdesc *sc_txq; @@ -331,8 +331,8 @@ int vic_alloc_dmamem(struct vic_softc *); void vic_free_dmamem(struct vic_softc *); void vic_link_state(struct vic_softc *); -void vic_rx_fill(struct vic_softc *); -void vic_rx_proc(struct vic_softc *); +void vic_rx_fill(struct vic_softc *, int); +void vic_rx_proc(struct vic_softc *, int); void vic_tx_proc(struct vic_softc *); void vic_iff(struct vic_softc *); void vic_getlladdr(struct vic_softc *); @@ -350,7 +350,7 @@ void vic_tick(void *); #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) -struct mbuf *vic_alloc_mbuf(struct vic_softc *, bus_dmamap_t); +struct mbuf *vic_alloc_mbuf(struct vic_softc *, bus_dmamap_t, u_int); const struct pci_matchid vic_devices[] = { { PCI_VENDOR_VMWARE, PCI_PRODUCT_VMWARE_NET } @@ -563,13 +563,18 @@ vic_alloc_data(struct vic_softc *sc) u_int8_t *kva; u_int offset; struct vic_rxdesc *rxd; - int i; + int i, q; - sc->sc_rxbuf = malloc(sizeof(struct vic_rxbuf) * sc->sc_nrxbuf, - M_DEVBUF, M_NOWAIT); - if (sc->sc_rxbuf == NULL) { - printf(": unable to allocate rxbuf\n"); - goto err; + sc->sc_rxq[0].pktlen = MCLBYTES; + sc->sc_rxq[1].pktlen = 4096; /* XXX VIC_JUMBO_FRAMELEN; */ + + for (q = 0; q < VIC_NRXRINGS; q++) { + sc->sc_rxq[q].bufs = malloc(sizeof(struct vic_rxbuf) * + sc->sc_nrxbuf, M_DEVBUF, M_NOWAIT | M_ZERO); + if (sc->sc_rxq[i].bufs == NULL) { + printf(": unable to allocate rxbuf for ring %d\n", q); + goto freerx; + } } sc->sc_txbuf = malloc(sizeof(struct vic_txbuf) * sc->sc_ntxbuf, @@ -598,37 +603,22 @@ vic_alloc_data(struct vic_softc *sc) 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++) { - rxd = &sc->sc_rxq[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 dummy rx ring 2 with an unusable entry */ - sc->sc_rxq2 = (struct vic_rxdesc *)&kva[offset]; + for (q = 0; q < VIC_NRXRINGS; q++) { + sc->sc_rxq[q].slots = (struct vic_rxdesc *)&kva[offset]; + sc->sc_data->vd_rx_offset[q] = offset; + sc->sc_data->vd_rx[q].length = sc->sc_nrxbuf; - sc->sc_data->vd_rx_offset2 = offset; - sc->sc_data->vd_rx_length2 = VIC_QUEUE2_SIZE; + for (i = 0; i < sc->sc_nrxbuf; i++) { + rxd = &sc->sc_rxq[q].slots[i]; - 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; + rxd->rx_physaddr = 0; + rxd->rx_buflength = 0; + rxd->rx_length = 0; + rxd->rx_owner = VIC_OWNER_DRIVER; - offset += sizeof(struct vic_rxdesc); + offset += sizeof(struct vic_rxdesc); + } } /* set up the tx ring */ @@ -640,23 +630,26 @@ vic_alloc_data(struct vic_softc *sc) return (0); freetx: free(sc->sc_txbuf, M_DEVBUF); + q = VIC_NRXRINGS; freerx: - free(sc->sc_rxbuf, M_DEVBUF); -err: + while (q--) + free(sc->sc_rxq[q].bufs, M_DEVBUF); + return (1); } void -vic_rx_fill(struct vic_softc *sc) +vic_rx_fill(struct vic_softc *sc, int q) { struct vic_rxbuf *rxb; struct vic_rxdesc *rxd; - while (sc->sc_rxq_len < sc->sc_data->vd_rx_length) { - rxb = &sc->sc_rxbuf[sc->sc_rxq_end]; - rxd = &sc->sc_rxq[sc->sc_rxq_end]; + while (sc->sc_rxq[q].len < sc->sc_data->vd_rx[q].length) { + rxb = &sc->sc_rxq[q].bufs[sc->sc_rxq[q].end]; + rxd = &sc->sc_rxq[q].slots[sc->sc_rxq[q].end]; - rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_dmamap); + rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_dmamap, + sc->sc_rxq[q].pktlen); if (rxb->rxb_m == NULL) break; @@ -668,8 +661,8 @@ vic_rx_fill(struct vic_softc *sc) rxd->rx_length = 0; rxd->rx_owner = VIC_OWNER_NIC; - VIC_INC(sc->sc_rxq_end, sc->sc_data->vd_rx_length); - sc->sc_rxq_len++; + VIC_INC(sc->sc_rxq[q].end, sc->sc_data->vd_rx[q].length); + sc->sc_rxq[q].len++; } } @@ -680,35 +673,39 @@ vic_init_data(struct vic_softc *sc) struct vic_rxdesc *rxd; struct vic_txbuf *txb; - int i; + int q, i; - for (i = 0; i < sc->sc_nrxbuf; i++) { - rxb = &sc->sc_rxbuf[i]; - rxd = &sc->sc_rxq[i]; + for (q = 0; q < VIC_NRXRINGS; q++) { + for (i = 0; i < sc->sc_nrxbuf; i++) { + rxb = &sc->sc_rxq[q].bufs[i]; + rxd = &sc->sc_rxq[q].slots[i]; - if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, - MCLBYTES, 0, BUS_DMA_NOWAIT, &rxb->rxb_dmamap) != 0) { - printf("%s: unable to create dmamap for rxb %d\n", - DEVNAME(sc), i); - goto freerxbs; + if (bus_dmamap_create(sc->sc_dmat, + sc->sc_rxq[q].pktlen, 1, sc->sc_rxq[q].pktlen, 0, + BUS_DMA_NOWAIT, &rxb->rxb_dmamap) != 0) { + printf("%s: unable to create dmamap for " + "ring %d slot %d\n", DEVNAME(sc), q, i); + goto freerxbs; + } + + /* scrub the ring */ + rxd->rx_physaddr = 0; + rxd->rx_buflength = 0; + rxd->rx_length = 0; + rxd->rx_owner = VIC_OWNER_DRIVER; } - /* scrub the ring */ - rxd->rx_physaddr = 0; - rxd->rx_buflength = 0; - rxd->rx_length = 0; - rxd->rx_owner = VIC_OWNER_DRIVER; + sc->sc_rxq[q].len = 0; + sc->sc_rxq[q].end = 0; + vic_rx_fill(sc, q); } - sc->sc_rxq_len = 0; - sc->sc_rxq_end = 0; - vic_rx_fill(sc); - for (i = 0; i < sc->sc_ntxbuf; i++) { txb = &sc->sc_txbuf[i]; - if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, + if (bus_dmamap_create(sc->sc_dmat, VIC_JUMBO_FRAMELEN, (sc->sc_cap & VIC_CMD_HWCAP_SG) ? VIC_SG_MAX : 1, - MCLBYTES, 0, BUS_DMA_NOWAIT, &txb->txb_dmamap) != 0) { + VIC_JUMBO_FRAMELEN, 0, BUS_DMA_NOWAIT, + &txb->txb_dmamap) != 0) { printf("%s: unable to create dmamap for tx %d\n", DEVNAME(sc), i); goto freetxbs; @@ -725,19 +722,23 @@ freetxbs: } i = sc->sc_nrxbuf; + q = VIC_NRXRINGS; freerxbs: - while (i--) { - rxb = &sc->sc_rxbuf[i]; - - if (rxb->rxb_m != NULL) { - 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); - m_freem(rxb->rxb_m); - rxb->rxb_m = NULL; + do { + while (i--) { + rxb = &sc->sc_rxq[q].bufs[i]; + + if (rxb->rxb_m != NULL) { + 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); + m_freem(rxb->rxb_m); + rxb->rxb_m = NULL; + } + bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap); } - bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap); - } + } while (--q); return (1); } @@ -749,20 +750,23 @@ vic_uninit_data(struct vic_softc *sc) struct vic_rxdesc *rxd; struct vic_txbuf *txb; - int i; + int i, q; - for (i = 0; i < sc->sc_nrxbuf; i++) { - rxb = &sc->sc_rxbuf[i]; - rxd = &sc->sc_rxq[i]; + for (q = 0; q < VIC_NRXRINGS; q++) { + for (i = 0; i < sc->sc_nrxbuf; i++) { + rxb = &sc->sc_rxq[q].bufs[i]; + rxd = &sc->sc_rxq[q].slots[i]; - if (rxb->rxb_m != NULL) { - 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); - m_freem(rxb->rxb_m); - rxb->rxb_m = NULL; + if (rxb->rxb_m != NULL) { + 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); + m_freem(rxb->rxb_m); + rxb->rxb_m = NULL; + } + bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap); } - bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap); } for (i = 0; i < sc->sc_ntxbuf; i++) { @@ -801,8 +805,10 @@ int vic_intr(void *arg) { struct vic_softc *sc = (struct vic_softc *)arg; + int q; - vic_rx_proc(sc); + for (q = 0; q < VIC_NRXRINGS; q++) + vic_rx_proc(sc, q); vic_tx_proc(sc); vic_write(sc, VIC_CMD, VIC_CMD_INTR_ACK); @@ -811,7 +817,7 @@ vic_intr(void *arg) } void -vic_rx_proc(struct vic_softc *sc) +vic_rx_proc(struct vic_softc *sc, int q) { struct ifnet *ifp = &sc->sc_ac.ac_if; struct vic_rxdesc *rxd; @@ -825,9 +831,9 @@ vic_rx_proc(struct vic_softc *sc) bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - while (sc->sc_rxq_len > 0) { - idx = sc->sc_data->vd_rx_nextidx; - if (idx >= sc->sc_data->vd_rx_length) { + while (sc->sc_rxq[q].len > 0) { + idx = sc->sc_data->vd_rx[q].nextidx; + if (idx >= sc->sc_data->vd_rx[q].length) { ifp->if_ierrors++; if (ifp->if_flags & IFF_DEBUG) printf("%s: receive index error\n", @@ -835,11 +841,11 @@ vic_rx_proc(struct vic_softc *sc) break; } - rxd = &sc->sc_rxq[idx]; + rxd = &sc->sc_rxq[q].slots[idx]; if (rxd->rx_owner != VIC_OWNER_DRIVER) break; - rxb = &sc->sc_rxbuf[idx]; + rxb = &sc->sc_rxq[q].bufs[idx]; if (rxb->rxb_m == NULL) { ifp->if_ierrors++; @@ -851,22 +857,17 @@ vic_rx_proc(struct vic_softc *sc) rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap); + m = rxb->rxb_m; + rxb->rxb_m = NULL; len = rxd->rx_length; + if (len < VIC_MIN_FRAMELEN) { - m = rxb->rxb_m; m_freem(m); - rxd->rx_owner = VIC_OWNER_DRIVER; - rxd->rx_length = 0; - - rxb->rxb_m = NULL; - ifp->if_iqdrops++; goto nextp; } - m = rxb->rxb_m; - rxb->rxb_m = NULL; m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = len; @@ -880,11 +881,12 @@ vic_rx_proc(struct vic_softc *sc) ether_input_mbuf(ifp, m); nextp: - sc->sc_rxq_len--; - VIC_INC(sc->sc_data->vd_rx_nextidx, sc->sc_data->vd_rx_length); + sc->sc_rxq[q].len--; + VIC_INC(sc->sc_data->vd_rx[q].nextidx, + sc->sc_data->vd_rx[q].length); } - vic_rx_fill(sc); + vic_rx_fill(sc, q); bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -1159,7 +1161,7 @@ vic_load_txb(struct vic_softc *sc, struct vic_txbuf *txb, struct mbuf *m) if (m0 == NULL) return (ENOBUFS); if (m->m_pkthdr.len > MHLEN) { - MCLGET(m0, M_DONTWAIT); + MCLGETI(m0, M_DONTWAIT, NULL, m->m_pkthdr.len); if (!(m0->m_flags & M_EXT)) { m_freem(m0); return (ENOBUFS); @@ -1284,19 +1286,19 @@ void vic_init(struct ifnet *ifp) { struct vic_softc *sc = (struct vic_softc *)ifp->if_softc; + int q; int s; 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; + for (q = 0; q < VIC_NRXRINGS; q++) { + sc->sc_data->vd_rx[q].nextidx = 0; + sc->sc_data->vd_rx_saved_nextidx[q] = 0; + } + if (vic_init_data(sc) != 0) return; @@ -1354,7 +1356,7 @@ vic_stop(struct ifnet *ifp) } struct mbuf * -vic_alloc_mbuf(struct vic_softc *sc, bus_dmamap_t map) +vic_alloc_mbuf(struct vic_softc *sc, bus_dmamap_t map, u_int pktlen) { struct mbuf *m = NULL; @@ -1362,13 +1364,13 @@ vic_alloc_mbuf(struct vic_softc *sc, bus_dmamap_t map) if (m == NULL) return (NULL); - MCLGETI(m, M_DONTWAIT, &sc->sc_ac.ac_if, MCLBYTES); + MCLGETI(m, M_DONTWAIT, &sc->sc_ac.ac_if, pktlen); if ((m->m_flags & M_EXT) == 0) { m_freem(m); return (NULL); } m->m_data += ETHER_ALIGN; - m->m_len = m->m_pkthdr.len = MCLBYTES - ETHER_ALIGN; + m->m_len = m->m_pkthdr.len = pktlen - ETHER_ALIGN; if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT) != 0) { printf("%s: could not load mbuf DMA map", DEVNAME(sc)); |