Date: Mon, 15 Jul 2013 02:19:38 +0000 (UTC) From: Bryan Venteicher <bryanv@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r253348 - projects/vmxnet/sys/dev/vmware/vmxnet3 Message-ID: <201307150219.r6F2Jcr1094588@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307150219.r6F2Jcr1094588>