summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_vic.c264
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));