From 704b62870b417f0401ec5576113c809065f70359 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Tue, 27 Dec 2011 13:43:09 +0800 Subject: [PATCH] emx: Use MSI, if device supports it --- sys/dev/netif/emx/if_emx.c | 42 +++++++++++++++++++++++++++++++++----- sys/dev/netif/emx/if_emx.h | 4 ++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/sys/dev/netif/emx/if_emx.c b/sys/dev/netif/emx/if_emx.c index fe8e03cd59..83e7bbbe66 100644 --- a/sys/dev/netif/emx/if_emx.c +++ b/sys/dev/netif/emx/if_emx.c @@ -276,12 +276,13 @@ DRIVER_MODULE(if_emx, pci, emx_driver, emx_devclass, NULL, NULL); static int emx_int_throttle_ceil = EMX_DEFAULT_ITR; static int emx_rxd = EMX_DEFAULT_RXD; static int emx_txd = EMX_DEFAULT_TXD; -static int emx_smart_pwr_down = FALSE; +static int emx_smart_pwr_down = 0; /* Controls whether promiscuous also shows bad packets */ static int emx_debug_sbp = FALSE; -static int emx_82573_workaround = TRUE; +static int emx_82573_workaround = 1; +static int emx_msi_enable = 1; TUNABLE_INT("hw.emx.int_throttle_ceil", &emx_int_throttle_ceil); TUNABLE_INT("hw.emx.rxd", &emx_rxd); @@ -289,6 +290,7 @@ TUNABLE_INT("hw.emx.txd", &emx_txd); TUNABLE_INT("hw.emx.smart_pwr_down", &emx_smart_pwr_down); TUNABLE_INT("hw.emx.sbp", &emx_debug_sbp); TUNABLE_INT("hw.emx.82573_workaround", &emx_82573_workaround); +TUNABLE_INT("hw.emx.msi.enable", &emx_msi_enable); /* Global used in WOL setup with multiport cards */ static int emx_global_quad_port_a = 0; @@ -398,8 +400,10 @@ emx_attach(device_t dev) { struct emx_softc *sc = device_get_softc(dev); struct ifnet *ifp = &sc->arpcom.ac_if; - int error = 0, i; + int error = 0, i, msi_enable; + u_int intr_flags; uint16_t eeprom_data, device_id, apme_mask; + char env[64]; lwkt_serialize_init(&sc->main_serialize); lwkt_serialize_init(&sc->tx_serialize); @@ -452,12 +456,37 @@ emx_attach(device_t dev) /* * Allocate interrupt */ + msi_enable = emx_msi_enable; + ksnprintf(env, sizeof(env), "hw.%s.msi.enable", + device_get_nameunit(dev)); + kgetenv_int(env, &msi_enable); + sc->intr_rid = 0; + sc->intr_type = EMX_INTR_TYPE_LEGACY; + intr_flags = RF_SHAREABLE | RF_ACTIVE; + + if (msi_enable) { + int cpu = -1; + + ksnprintf(env, sizeof(env), "hw.%s.msi.cpu", + device_get_nameunit(dev)); + kgetenv_int(env, &cpu); + if (cpu >= ncpus) + cpu = ncpus - 1; + + if (pci_alloc_msi(dev, &sc->intr_rid, 1, cpu) == 0) { + intr_flags &= ~RF_SHAREABLE; + sc->intr_type = EMX_INTR_TYPE_MSI; + } + } + sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->intr_rid, - RF_SHAREABLE | RF_ACTIVE); + intr_flags); if (sc->intr_res == NULL) { device_printf(dev, "Unable to allocate bus resource: " "interrupt\n"); + if (sc->intr_rid != 0) + pci_release_msi(dev); error = ENXIO; goto fail; } @@ -686,7 +715,7 @@ emx_attach(device_t dev) goto fail; } - ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->intr_res)); + ifp->if_cpuid = rman_get_cpuid(sc->intr_res); KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus); return (0); fail: @@ -732,6 +761,9 @@ emx_detach(device_t dev) sc->intr_res); } + if (sc->intr_type == EMX_INTR_TYPE_MSI) + pci_release_msi(dev); + if (sc->memory != NULL) { bus_release_resource(dev, SYS_RES_MEMORY, sc->memory_rid, sc->memory); diff --git a/sys/dev/netif/emx/if_emx.h b/sys/dev/netif/emx/if_emx.h index af52c83ecf..37639f916e 100644 --- a/sys/dev/netif/emx/if_emx.h +++ b/sys/dev/netif/emx/if_emx.h @@ -252,6 +252,7 @@ struct emx_softc { struct resource *intr_res; void *intr_tag; int intr_rid; + int intr_type; struct ifmedia media; struct callout timer; @@ -376,6 +377,9 @@ struct emx_softc { struct e1000_hw_stats stats; }; +#define EMX_INTR_TYPE_LEGACY 0 +#define EMX_INTR_TYPE_MSI 1 + struct emx_txbuf { struct mbuf *m_head; bus_dmamap_t map; -- 2.41.0