svn commit: r253348 - projects/vmxnet/sys/dev/vmware/vmxnet3

Bryan Venteicher bryanv at FreeBSD.org
Mon Jul 15 02:19:39 UTC 2013


Author: bryanv
Date: Mon Jul 15 02:19:38 2013
New Revision: 253348
URL: http://svnweb.freebsd.org/changeset/base/253348

Log:
  Add MSI/MSIX support

Modified:
  projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c
  projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxreg.h
  projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h

Modified: projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c
==============================================================================
--- projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c	Mon Jul 15 01:41:34 2013	(r253347)
+++ projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c	Mon Jul 15 02:19:38 2013	(r253348)
@@ -80,11 +80,26 @@ static void	vmxnet3_free_resources(struc
 static int	vmxnet3_check_version(struct vmxnet3_softc *);
 static void	vmxnet3_initial_config(struct vmxnet3_softc *);
 
+static int	vmxnet3_alloc_msix_interrupts(struct vmxnet3_softc *);
+static int	vmxnet3_alloc_msi_interrupts(struct vmxnet3_softc *);
+static int	vmxnet3_alloc_legacy_interrupts(struct vmxnet3_softc *);
+static int	vmxnet3_alloc_interrupt(struct vmxnet3_softc *, int, int,
+		    struct vmxnet3_interrupt *);
+static int	vmxnet3_alloc_intr_resources(struct vmxnet3_softc *);
+static int	vmxnet3_setup_msix_interrupts(struct vmxnet3_softc *);
+static int	vmxnet3_setup_legacy_interrupt(struct vmxnet3_softc *);
+static int	vmxnet3_setup_interrupts(struct vmxnet3_softc *);
+static int	vmxnet3_alloc_interrupts(struct vmxnet3_softc *);
+
+static void	vmxnet3_free_interrupt(struct vmxnet3_softc *,
+		    struct vmxnet3_interrupt *);
+static void 	vmxnet3_free_interrupts(struct vmxnet3_softc *);
+
 static int	vmxnet3_init_rxq(struct vmxnet3_softc *, int);
 static int	vmxnet3_init_txq(struct vmxnet3_softc *, int);
 static int	vmxnet3_alloc_rxtx_queues(struct vmxnet3_softc *);
 static void	vmxnet3_destroy_rxq(struct vmxnet3_rxqueue *);
-static void 	vmxnet3_destroy_txq(struct vmxnet3_txqueue *);
+static void	vmxnet3_destroy_txq(struct vmxnet3_txqueue *);
 static void	vmxnet3_free_rxtx_queues(struct vmxnet3_softc *);
 
 static int	vmxnet3_alloc_shared_data(struct vmxnet3_softc *);
@@ -108,7 +123,9 @@ static void	vmxnet3_rx_csum(struct vmxne
 static int	vmxnet3_newbuf(struct vmxnet3_softc *, struct vmxnet3_rxring *);
 static void	vmxnet3_rxeof(struct vmxnet3_softc *, struct vmxnet3_rxqueue *);
 static void	vmxnet3_legacy_intr(void *);
-static int	vmxnet3_setup_interrupts(struct vmxnet3_softc *);
+static void	vmxnet3_txq_intr(void *);
+static void	vmxnet3_rxq_intr(void *);
+static void	vmxnet3_event_intr(void *);
 
 static void	vmxnet3_txstop(struct vmxnet3_softc *, struct vmxnet3_txqueue *);
 static void	vmxnet3_rxstop(struct vmxnet3_softc *, struct vmxnet3_rxqueue *);
@@ -119,7 +136,7 @@ static int	vmxnet3_rxinit(struct vmxnet3
 static int	vmxnet3_reinit_queues(struct vmxnet3_softc *);
 static int	vmxnet3_enable_device(struct vmxnet3_softc *);
 static void	vmxnet3_reinit_rxfilters(struct vmxnet3_softc *);
-static int 	vmxnet3_reinit(struct vmxnet3_softc *);
+static int	vmxnet3_reinit(struct vmxnet3_softc *);
 static void	vmxnet3_init_locked(struct vmxnet3_softc *);
 static void	vmxnet3_init(void *);
 
@@ -136,8 +153,8 @@ static void	vmxnet3_start(struct ifnet *
 
 static void	vmxnet3_update_vlan_filter(struct vmxnet3_softc *, int,
 		    uint16_t);
-static void 	vmxnet3_register_vlan(void *, struct ifnet *, uint16_t);
-static void 	vmxnet3_unregister_vlan(void *, struct ifnet *, uint16_t);
+static void	vmxnet3_register_vlan(void *, struct ifnet *, uint16_t);
+static void	vmxnet3_unregister_vlan(void *, struct ifnet *, uint16_t);
 static void	vmxnet3_set_rxfilter(struct vmxnet3_softc *);
 static int	vmxnet3_change_mtu(struct vmxnet3_softc *, int);
 static int	vmxnet3_ioctl(struct ifnet *, u_long, caddr_t);
@@ -231,6 +248,10 @@ vmxnet3_attach(device_t dev)
 	if (error)
 		goto fail;
 
+	error = vmxnet3_alloc_interrupts(sc);
+	if (error)
+		goto fail;
+
 	error = vmxnet3_alloc_data(sc);
 	if (error)
 		goto fail;
@@ -272,11 +293,6 @@ vmxnet3_detach(device_t dev)
 		callout_drain(&sc->vmx_tick);
 	}
 
-	if (sc->vmx_intrhand != NULL) {
-		bus_teardown_intr(dev, sc->vmx_irq, sc->vmx_intrhand);
-		sc->vmx_intrhand = NULL;
-	}
-
 	if (sc->vmx_vlan_attach != NULL) {
 		EVENTHANDLER_DEREGISTER(vlan_config, sc->vmx_vlan_attach);
 		sc->vmx_vlan_attach = NULL;
@@ -286,6 +302,8 @@ vmxnet3_detach(device_t dev)
 		sc->vmx_vlan_detach = NULL;
 	}
 
+	vmxnet3_free_interrupts(sc);
+
 	if (ifp != NULL) {
 		if_free(ifp);
 		sc->vmx_ifp = NULL;
@@ -293,11 +311,6 @@ vmxnet3_detach(device_t dev)
 
 	ifmedia_removeall(&sc->vmx_media);
 
-	if (sc->vmx_irq != NULL) {
-		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vmx_irq);
-		sc->vmx_irq = NULL;
-	}
-
 	vmxnet3_free_data(sc);
 	vmxnet3_free_resources(sc);
 	vmxnet3_free_rxtx_queues(sc);
@@ -346,18 +359,15 @@ vmxnet3_alloc_resources(struct vmxnet3_s
 	sc->vmx_iot1 = rman_get_bustag(sc->vmx_res1);
 	sc->vmx_ioh1 = rman_get_bushandle(sc->vmx_res1);
 
-	/*
-	 * XXX This really doesn't belong here, but is fine until
-	 * we support MSI/MSIX.
-	 */
-	rid = 0;
-	sc->vmx_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-	   RF_SHAREABLE | RF_ACTIVE);
-	if (sc->vmx_irq == NULL) {
-		device_printf(dev, "could not allocate interrupt resource\n");
-		return (ENXIO);
+	if (pci_find_cap(dev, PCIY_MSIX, NULL) == 0) {
+		rid = PCIR_BAR(2);
+		sc->vmx_msix_res = bus_alloc_resource_any(dev,
+		    SYS_RES_MEMORY, &rid, RF_ACTIVE);
 	}
 
+	if (sc->vmx_msix_res == NULL)
+		sc->vmx_flags |= VMXNET3_FLAG_NO_MSIX;
+
 	return (0);
 }
 
@@ -380,6 +390,13 @@ vmxnet3_free_resources(struct vmxnet3_so
 		bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->vmx_res1);
 		sc->vmx_res1 = NULL;
 	}
+
+	if (sc->vmx_msix_res != NULL) {
+		rid = PCIR_BAR(2);
+		bus_release_resource(dev, SYS_RES_MEMORY, rid,
+		    sc->vmx_msix_res);
+		sc->vmx_msix_res = NULL;
+	}
 }
 
 static int
@@ -402,7 +419,7 @@ vmxnet3_check_version(struct vmxnet3_sof
 	if ((version & 0x01) == 0) {
 		device_printf(dev, "unsupported UPT version %#x\n", version);
 		return (ENOTSUP);
-	} else 
+	} else
 		vmxnet3_write_bar1(sc, VMXNET3_BAR1_UVRS, 1);
 
 	return (0);
@@ -420,6 +437,305 @@ vmxnet3_initial_config(struct vmxnet3_so
 }
 
 static int
+vmxnet3_alloc_msix_interrupts(struct vmxnet3_softc *sc)
+{
+	device_t dev;
+	int nmsix, cnt, required;
+
+	dev = sc->vmx_dev;
+
+	if (sc->vmx_flags & VMXNET3_FLAG_NO_MSIX)
+		return (1);
+
+	/* Allocate an additional vector for the events interrupt. */
+	required = sc->vmx_nrxqueues + sc->vmx_ntxqueues + 1;
+
+	nmsix = pci_msix_count(dev);
+	if (nmsix < required)
+		return (1);
+
+	int error;
+
+	cnt = required;
+	if ((error = pci_alloc_msix(dev, &cnt)) == 0 && cnt >= required) {
+		sc->vmx_nintrs = required;
+		return (0);
+	}
+
+	pci_release_msi(dev);
+	return (1);
+}
+
+static int
+vmxnet3_alloc_msi_interrupts(struct vmxnet3_softc *sc)
+{
+	device_t dev;
+	int nmsi, cnt, required;
+
+	dev = sc->vmx_dev;
+	required = 1;
+
+	nmsi = pci_msi_count(dev);
+	if (nmsi < required)
+		return (1);
+
+	cnt = required;
+	if (pci_alloc_msi(dev, &cnt) == 0 && cnt >= required) {
+		sc->vmx_nintrs = 1;
+		return (0);
+	}
+
+	pci_release_msi(dev);
+	return (1);
+}
+
+static int
+vmxnet3_alloc_legacy_interrupts(struct vmxnet3_softc *sc)
+{
+
+	sc->vmx_nintrs = 1;
+	return (0);
+}
+
+static int
+vmxnet3_alloc_interrupt(struct vmxnet3_softc *sc, int rid, int flags,
+    struct vmxnet3_interrupt *intr)
+{
+	struct resource *irq;
+	int old_rid = rid;
+
+	irq = bus_alloc_resource_any(sc->vmx_dev, SYS_RES_IRQ, &rid, flags);
+	if (irq == NULL)
+		return (ENXIO);
+
+	intr->vmxi_irq = irq;
+	intr->vmxi_rid = rid;
+
+	return (0);
+}
+
+static int
+vmxnet3_alloc_intr_resources(struct vmxnet3_softc *sc)
+{
+	int i, rid, flags, error;
+
+	rid = 0;
+	flags = RF_ACTIVE;
+
+	if (sc->vmx_intr_type == VMXNET3_IT_LEGACY)
+		flags |= RF_SHAREABLE;
+	else
+		rid = 1;
+
+	for (i = 0; i < sc->vmx_nintrs; i++, rid++) {
+		error = vmxnet3_alloc_interrupt(sc, rid, flags,
+		    &sc->vmx_intrs[i]);
+		if (error)
+			return (error);
+	}
+
+	return (0);
+}
+
+/*
+ * NOTE: We only support the simple case of each Rx and Tx queue on its
+ * own MSIX vector. This is good enough until we support mulitqueue.
+ */
+static int
+vmxnet3_setup_msix_interrupts(struct vmxnet3_softc *sc)
+{
+	device_t dev;
+	struct vmxnet3_txqueue *txq;
+	struct vmxnet3_rxqueue *rxq;
+	struct vmxnet3_interrupt *intr;
+	enum intr_type type;
+	int i, error;
+
+	dev = sc->vmx_dev;
+	intr = &sc->vmx_intrs[0];
+	type = INTR_TYPE_NET | INTR_MPSAFE;
+
+	for (i = 0; i < sc->vmx_ntxqueues; i++, intr++) {
+		txq = &sc->vmx_txq[i];
+		error = bus_setup_intr(dev, intr->vmxi_irq, type, NULL,
+		     vmxnet3_txq_intr, txq, &intr->vmxi_handler);
+		if (error)
+			return (error);
+		txq->vxtxq_intr_idx = intr->vmxi_rid - 1;
+	}
+
+	for (i = 0; i < sc->vmx_nrxqueues; i++, intr++) {
+		rxq = &sc->vmx_rxq[i];
+		error = bus_setup_intr(dev, intr->vmxi_irq, type, NULL,
+		    vmxnet3_rxq_intr, rxq, &intr->vmxi_handler);
+		if (error)
+			return (error);
+		rxq->vxrxq_intr_idx = intr->vmxi_rid - 1;
+	}
+
+	error = bus_setup_intr(dev, intr->vmxi_irq, type, NULL,
+	    vmxnet3_event_intr, sc, &intr->vmxi_handler);
+	if (error)
+		return (error);
+	sc->vmx_event_intr_idx = intr->vmxi_rid - 1;
+
+	return (0);
+}
+
+static int
+vmxnet3_setup_legacy_interrupt(struct vmxnet3_softc *sc)
+{
+	struct vmxnet3_interrupt *intr;
+	int i, error;
+
+	intr = &sc->vmx_intrs[0];
+	error = bus_setup_intr(sc->vmx_dev, intr->vmxi_irq,
+	    INTR_TYPE_NET | INTR_MPSAFE, NULL, vmxnet3_legacy_intr, sc,
+	    &intr->vmxi_handler);
+
+	for (i = 0; i < sc->vmx_ntxqueues; i++)
+		sc->vmx_txq[i].vxtxq_intr_idx = 0;
+	for (i = 0; i < sc->vmx_nrxqueues; i++)
+		sc->vmx_rxq[i].vxrxq_intr_idx = 0;
+	sc->vmx_event_intr_idx = 0;
+
+	return (error);
+}
+
+/*
+ * XXX BMV Should probably reorganize the attach and just do
+ * this in vmxnet3_init_shared_data().
+ */
+static void
+vmxnet3_set_interrupt_idx(struct vmxnet3_softc *sc)
+{
+	struct vmxnet3_txqueue *txq;
+	struct vmxnet3_txq_shared *txs;
+	struct vmxnet3_rxqueue *rxq;
+	struct vmxnet3_rxq_shared *rxs;
+	int i;
+
+	sc->vmx_ds->evintr = sc->vmx_event_intr_idx;
+
+	for (i = 0; i < sc->vmx_ntxqueues; i++) {
+		txq = &sc->vmx_txq[i];
+		txs = txq->vxtxq_ts;
+		txs->intr_idx = txq->vxtxq_intr_idx;
+	}
+
+	for (i = 0; i < sc->vmx_nrxqueues; i++) {
+		rxq = &sc->vmx_rxq[i];
+		rxs = rxq->vxrxq_rs;
+		rxs->intr_idx = rxq->vxrxq_intr_idx;
+	}
+}
+
+static int
+vmxnet3_setup_interrupts(struct vmxnet3_softc *sc)
+{
+	int error;
+
+	error = vmxnet3_alloc_intr_resources(sc);
+	if (error)
+		return (error);
+
+	switch (sc->vmx_intr_type) {
+	case VMXNET3_IT_MSIX:
+		error = vmxnet3_setup_msix_interrupts(sc);
+		break;
+	case VMXNET3_IT_MSI:
+	case VMXNET3_IT_LEGACY:
+		error = vmxnet3_setup_legacy_interrupt(sc);
+		break;
+	default:
+		panic("%s: invalid interrupt type %d", __func__,
+		    sc->vmx_intr_type);
+	}
+
+	if (error == 0)
+		vmxnet3_set_interrupt_idx(sc);
+
+	return (error);
+}
+
+static int
+vmxnet3_alloc_interrupts(struct vmxnet3_softc *sc)
+{
+	device_t dev;
+	uint32_t config;
+	int error;
+
+	dev = sc->vmx_dev;
+	config = vmxnet3_read_cmd(sc, VMXNET3_CMD_GET_INTRCFG);
+
+	sc->vmx_intr_type = config & 0x03;
+	sc->vmx_intr_mask_mode = (config >> 2) & 0x03;
+
+	switch (sc->vmx_intr_type) {
+	case VMXNET3_IT_AUTO:
+		sc->vmx_intr_type = VMXNET3_IT_MSIX;
+		/* FALLTHROUGH */
+	case VMXNET3_IT_MSIX:
+		error = vmxnet3_alloc_msix_interrupts(sc);
+		if (error == 0)
+			break;
+		sc->vmx_intr_type = VMXNET3_IT_MSI;
+		/* FALLTHROUGH */
+	case VMXNET3_IT_MSI:
+		error = vmxnet3_alloc_msi_interrupts(sc);
+		if (error == 0)
+			break;
+		sc->vmx_intr_type = VMXNET3_IT_LEGACY;
+		/* FALLTHROUGH */
+	case VMXNET3_IT_LEGACY:
+		error = vmxnet3_alloc_legacy_interrupts(sc);
+		if (error == 0)
+			break;
+		/* FALLTHROUGH */
+	default:
+		sc->vmx_intr_type = -1;
+		device_printf(dev, "cannot allocate any interrupt resources\n");
+		return (ENXIO);
+	}
+
+	return (error);
+}
+
+static void
+vmxnet3_free_interrupt(struct vmxnet3_softc *sc,
+    struct vmxnet3_interrupt *intr)
+{
+	device_t dev;
+
+	dev = sc->vmx_dev;
+
+	if (intr->vmxi_handler != NULL) {
+		bus_teardown_intr(dev, intr->vmxi_irq, intr->vmxi_handler);
+		intr->vmxi_handler = NULL;
+	}
+
+	if (intr->vmxi_irq != NULL) {
+		bus_release_resource(dev, SYS_RES_IRQ, intr->vmxi_rid,
+		    intr->vmxi_irq);
+		intr->vmxi_irq = NULL;
+		intr->vmxi_rid = -1;
+	}
+}
+
+static void
+vmxnet3_free_interrupts(struct vmxnet3_softc *sc)
+{
+	int i;
+
+	for (i = 0; i < sc->vmx_nintrs; i++)
+		vmxnet3_free_interrupt(sc, &sc->vmx_intrs[i]);
+
+	if (sc->vmx_intr_type == VMXNET3_IT_MSI ||
+	    sc->vmx_intr_type == VMXNET3_IT_MSIX)
+		pci_release_msi(sc->vmx_dev);
+}
+
+static int
 vmxnet3_init_rxq(struct vmxnet3_softc *sc, int q)
 {
 	struct vmxnet3_rxqueue *rxq;
@@ -936,12 +1252,12 @@ vmxnet3_init_shared_data(struct vmxnet3_
 	ds->nrxsg_max = sc->vmx_max_rxsegs;
 
 	/* Interrupt control. */
-	ds->automask = 1;
-	ds->nintr = VMXNET3_NINTR;
-	ds->evintr = 0;
+	ds->automask = 1;	/* VMXNET3_IMM_AUTO */
+	ds->nintr = sc->vmx_nintrs;
+	ds->evintr = sc->vmx_event_intr_idx;
 	ds->ictrl = VMXNET3_ICTRL_DISABLE_ALL;
 
-	for (i = 0; i < VMXNET3_NINTR; i++)
+	for (i = 0; i < sc->vmx_nintrs; i++)
 		ds->modlevel[i] = UPT1_IMOD_ADAPTIVE;
 
 	/* Receive filter. */
@@ -1100,13 +1416,12 @@ vmxnet3_evintr(struct vmxnet3_softc *sc)
 
 	dev = sc->vmx_dev;
 	ifp = sc->vmx_ifp;
-	event = sc->vmx_ds->event;
 	reset = 0;
 
 	/* Clear events. */
-	vmxnet3_write_bar1(sc, VMXNET3_BAR1_EVENT, event);
-
 	VMXNET3_CORE_LOCK(sc);
+	event = sc->vmx_ds->event;
+	vmxnet3_write_bar1(sc, VMXNET3_BAR1_EVENT, event);
 
 	if (event & VMXNET3_EVENT_LINK)
 		vmxnet3_link_status(sc);
@@ -1378,8 +1693,10 @@ vmxnet3_legacy_intr(void *xsc)
 	txq = &sc->vmx_txq[0];
 	ifp = sc->vmx_ifp;
 
-	if (vmxnet3_read_bar1(sc, VMXNET3_BAR1_INTR) == 0)
-		return;
+	if (sc->vmx_intr_type == VMXNET3_IT_LEGACY) {
+		if (vmxnet3_read_bar1(sc, VMXNET3_BAR1_INTR) == 0)
+			return;
+	}
 
 	if (sc->vmx_ds->event != 0)
 		vmxnet3_evintr(sc);
@@ -1397,22 +1714,54 @@ vmxnet3_legacy_intr(void *xsc)
 	vmxnet3_enable_intr(sc, 0);
 }
 
-static int
-vmxnet3_setup_interrupts(struct vmxnet3_softc *sc)
+static void
+vmxnet3_txq_intr(void *xtxq)
 {
-	device_t dev;
-	int error;
+	struct vmxnet3_softc *sc;
+	struct vmxnet3_txqueue *txq;
+	struct ifnet *ifp;
 
-	dev = sc->vmx_dev;
+	txq = xtxq;
+	sc = txq->vxtxq_sc;
+	ifp = sc->vmx_ifp;
 
-	/*
-	 * Only support a single legacy interrupt for now.
-	 * Add MSI/MSIx later.
-	 */
-	error = bus_setup_intr(dev, sc->vmx_irq, INTR_TYPE_NET | INTR_MPSAFE,
-	    NULL, vmxnet3_legacy_intr, sc, &sc->vmx_intrhand);
+	VMXNET3_TXQ_LOCK(txq);
+	vmxnet3_txeof(sc, txq);
+	/* XXX We are not really multiqueue yet. */
+	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+		vmxnet3_start_locked(ifp);
+	VMXNET3_TXQ_UNLOCK(txq);
 
-	return (error);
+	vmxnet3_enable_intr(sc, txq->vxtxq_intr_idx);
+}
+
+static void
+vmxnet3_rxq_intr(void *xrxq)
+{
+	struct vmxnet3_softc *sc;
+	struct vmxnet3_rxqueue *rxq;
+
+	rxq = xrxq;
+	sc = rxq->vxrxq_sc;
+
+	VMXNET3_RXQ_LOCK(rxq);
+	vmxnet3_rxeof(sc, rxq);
+	VMXNET3_RXQ_UNLOCK(rxq);
+
+	vmxnet3_enable_intr(sc, rxq->vxrxq_intr_idx);
+}
+
+static void
+vmxnet3_event_intr(void *xsc)
+{
+	struct vmxnet3_softc *sc;
+
+	sc = xsc;
+
+	if (sc->vmx_ds->event != 0)
+		vmxnet3_evintr(sc);
+
+	vmxnet3_enable_intr(sc, sc->vmx_event_intr_idx);
 }
 
 static void
@@ -2307,7 +2656,7 @@ vmxnet3_enable_all_intrs(struct vmxnet3_
 	int i;
 
 	sc->vmx_ds->ictrl &= ~VMXNET3_ICTRL_DISABLE_ALL;
-	for (i = 0; i < VMXNET3_NINTR; i++)
+	for (i = 0; i < sc->vmx_nintrs; i++)
 		vmxnet3_enable_intr(sc, i);
 }
 
@@ -2317,7 +2666,7 @@ vmxnet3_disable_all_intrs(struct vmxnet3
 	int i;
 
 	sc->vmx_ds->ictrl |= VMXNET3_ICTRL_DISABLE_ALL;
-	for (i = 0; i < VMXNET3_NINTR; i++)
+	for (i = 0; i < sc->vmx_nintrs; i++)
 		vmxnet3_disable_intr(sc, i);
 }
 

Modified: projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxreg.h
==============================================================================
--- projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxreg.h	Mon Jul 15 01:41:34 2013	(r253347)
+++ projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxreg.h	Mon Jul 15 02:19:38 2013	(r253348)
@@ -83,6 +83,7 @@ struct UPT1_RxStats {
 #define VMXNET3_CMD_GET_LINK	0xF00D0002	/* Get link status */
 #define VMXNET3_CMD_GET_MACL	0xF00D0003	/* Get MAC address low */
 #define VMXNET3_CMD_GET_MACH	0xF00D0004	/* Get MAC address high */
+#define VMXNET3_CMD_GET_INTRCFG	0xF00D0008	/* Get interrupt config */
 
 #define VMXNET3_DMADESC_ALIGN	128
 #define VMXNET3_INIT_GEN	1
@@ -183,7 +184,6 @@ struct vmxnet3_rxcompdesc {
 
 #define VMXNET3_MAX_TX_QUEUES	8
 #define VMXNET3_MAX_RX_QUEUES	16
-#define VMXNET3_NINTR		1
 #define VMXNET3_MAX_INTRS \
     (VMXNET3_MAX_TX_QUEUES + VMXNET3_MAX_RX_QUEUES + 1)
 
@@ -204,6 +204,17 @@ struct vmxnet3_rxcompdesc {
 #define VMXNET3_MIN_MTU		60
 #define VMXNET3_MAX_MTU		9000
 
+/* Interrupt mask mode. */
+#define VMXNET3_IMM_AUTO	0x00
+#define VMXNET3_IMM_ACTIVE	0x01
+#define VMXNET3_IMM_LAZY	0x02
+
+/* Interrupt type. */
+#define VMXNET3_IT_AUTO		0x00
+#define VMXNET3_IT_LEGACY	0x01
+#define VMXNET3_IT_MSI		0x02
+#define VMXNET3_IT_MSIX		0x03
+
 struct vmxnet3_driver_shared {
 	uint32_t	magic;
 	uint32_t	pad1;

Modified: projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h
==============================================================================
--- projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h	Mon Jul 15 01:41:34 2013	(r253347)
+++ projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h	Mon Jul 15 02:19:38 2013	(r253348)
@@ -93,6 +93,7 @@ struct vmxnet3_txqueue {
 	struct mtx			 vxtxq_mtx;
 	struct vmxnet3_softc		*vxtxq_sc;
 	int				 vxtxq_id;
+	int				 vxtxq_intr_idx;
 	struct vmxnet3_txring		 vxtxq_cmd_ring;
 	struct vmxnet3_comp_ring	 vxtxq_comp_ring;
 	struct vmxnet3_txq_shared	*vxtxq_ts;
@@ -111,6 +112,7 @@ struct vmxnet3_rxqueue {
 	struct mtx			 vxrxq_mtx;
 	struct vmxnet3_softc		*vxrxq_sc;
 	int				 vxrxq_id;
+	int				 vxrxq_intr_idx;
 	struct vmxnet3_rxring		 vxrxq_cmd_ring[VMXNET3_RXRINGS_PERQ];
 	struct vmxnet3_comp_ring	 vxrxq_comp_ring;
 	struct vmxnet3_rxq_shared	*vxrxq_rs;
@@ -124,41 +126,52 @@ struct vmxnet3_rxqueue {
 #define VMXNET3_RXQ_LOCK_ASSERT_NOTOWNED(_rxq)	\
     mtx_assert(&(_rxq)->vxrxq_mtx, MA_NOTOWNED)
 
+struct vmxnet3_interrupt {
+	struct resource		*vmxi_irq;
+	int			 vmxi_rid;
+	void			*vmxi_handler;
+};
+
 struct vmxnet3_softc {
 	device_t			 vmx_dev;
 	struct ifnet			*vmx_ifp;
+	struct vmxnet3_driver_shared	*vmx_ds;
 	uint32_t			 vmx_flags;
+#define VMXNET3_FLAG_NO_MSIX	0x0001
 
 	struct vmxnet3_rxqueue		*vmx_rxq;
 	struct vmxnet3_txqueue		*vmx_txq;
 
-	int				 vmx_watchdog_timer;
-	int				 vmx_if_flags;
+	struct resource			*vmx_res0;
+	bus_space_tag_t			 vmx_iot0;
+	bus_space_handle_t		 vmx_ioh0;
+	struct resource			*vmx_res1;
+	bus_space_tag_t			 vmx_iot1;
+	bus_space_handle_t		 vmx_ioh1;
+	struct resource			*vmx_msix_res;
+
 	int				 vmx_link_active;
 	int				 vmx_link_speed;
-
+	int				 vmx_if_flags;
 	int				 vmx_ntxqueues;
 	int				 vmx_nrxqueues;
 	int				 vmx_ntxdescs;
 	int				 vmx_nrxdescs;
+	int				 vmx_watchdog_timer;
 	int				 vmx_max_rxsegs;
 
-	struct resource			*vmx_res0;
-	bus_space_tag_t			 vmx_iot0;
-	bus_space_handle_t		 vmx_ioh0;
-	struct resource			*vmx_res1;
-	bus_space_tag_t			 vmx_iot1;
-	bus_space_handle_t		 vmx_ioh1;
+	int				 vmx_intr_type;
+	int				 vmx_intr_mask_mode;
+	int				 vmx_event_intr_idx;
+	int				 vmx_nintrs;
+	struct vmxnet3_interrupt	 vmx_intrs[VMXNET3_MAX_INTRS];
 
 	struct mtx			 vmx_mtx;
+	uint8_t				*vmx_mcast;
+	void				*vmx_qs;
 	struct callout			 vmx_tick;
-	struct vmxnet3_driver_shared	*vmx_ds;
 	struct vmxnet3_dma_alloc	 vmx_ds_dma;
-	void				*vmx_qs;
 	struct vmxnet3_dma_alloc	 vmx_qs_dma;
-	struct resource			*vmx_irq;
-	void				*vmx_intrhand;
-	uint8_t				*vmx_mcast;
 	struct vmxnet3_dma_alloc	 vmx_mcast_dma;
 	struct ifmedia			 vmx_media;
 	eventhandler_tag		 vmx_vlan_attach;


More information about the svn-src-projects mailing list