diff options
author | yongari <yongari@FreeBSD.org> | 2009-11-19 21:45:06 +0000 |
---|---|---|
committer | yongari <yongari@FreeBSD.org> | 2009-11-19 21:45:06 +0000 |
commit | 16c3f5116048eb97b6cf8fc71db77ebf33213a55 (patch) | |
tree | 74286bc822303c53eeb95453aeb4553930f02a3f /sys/dev/et/if_et.c | |
parent | 2192f568cc5a5ff84e5052f89dbfd740b739fad5 (diff) | |
download | FreeBSD-src-16c3f5116048eb97b6cf8fc71db77ebf33213a55.zip FreeBSD-src-16c3f5116048eb97b6cf8fc71db77ebf33213a55.tar.gz |
Add MSI support.
Diffstat (limited to 'sys/dev/et/if_et.c')
-rw-r--r-- | sys/dev/et/if_et.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/sys/dev/et/if_et.c b/sys/dev/et/if_et.c index d9af586..e6e5d60 100644 --- a/sys/dev/et/if_et.c +++ b/sys/dev/et/if_et.c @@ -76,6 +76,10 @@ MODULE_DEPEND(et, pci, 1, 1, 1); MODULE_DEPEND(et, ether, 1, 1, 1); MODULE_DEPEND(et, miibus, 1, 1, 1); +/* Tunables. */ +static int msi_disable = 0; +TUNABLE_INT("hw.re.msi_disable", &msi_disable); + static int et_probe(device_t); static int et_attach(device_t); static int et_detach(device_t); @@ -230,7 +234,7 @@ et_attach(device_t dev) struct et_softc *sc; struct ifnet *ifp; uint8_t eaddr[ETHER_ADDR_LEN]; - int error; + int cap, error, msic; sc = device_get_softc(dev); sc->dev = dev; @@ -268,13 +272,38 @@ et_attach(device_t dev) sc->sc_mem_bt = rman_get_bustag(sc->sc_mem_res); sc->sc_mem_bh = rman_get_bushandle(sc->sc_mem_res); + msic = 0; + if (pci_find_extcap(dev, PCIY_EXPRESS, &cap) == 0) { + sc->sc_expcap = cap; + sc->sc_flags |= ET_FLAG_PCIE; + msic = pci_msi_count(dev); + if (bootverbose) + device_printf(dev, "MSI count : %d\n", msic); + } + if (msic > 0 && msi_disable == 0) { + msic = 1; + if (pci_alloc_msi(dev, &msic) == 0) { + if (msic == 1) { + device_printf(dev, "Using %d MSI message\n", + msic); + sc->sc_flags |= ET_FLAG_MSI; + } else + pci_release_msi(dev); + } + } + /* * Allocate IRQ */ - sc->sc_irq_rid = 0; - sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &sc->sc_irq_rid, - RF_SHAREABLE | RF_ACTIVE); + if ((sc->sc_flags & ET_FLAG_MSI) == 0) { + sc->sc_irq_rid = 0; + sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->sc_irq_rid, RF_SHAREABLE | RF_ACTIVE); + } else { + sc->sc_irq_rid = 1; + sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->sc_irq_rid, RF_ACTIVE); + } if (sc->sc_irq_res == NULL) { device_printf(dev, "can't allocate irq\n"); error = ENXIO; @@ -323,8 +352,7 @@ et_attach(device_t dev) callout_init_mtx(&sc->sc_tick, &sc->sc_mtx, 0); error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_NET | INTR_MPSAFE, - NULL, et_intr, sc, &sc->sc_irq_handle); - + NULL, et_intr, sc, &sc->sc_irq_handle); if (error) { ether_ifdetach(ifp); device_printf(dev, "can't setup intr\n"); @@ -363,6 +391,8 @@ et_detach(device_t dev) bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, sc->sc_irq_res); } + if ((sc->sc_flags & ET_FLAG_MSI) != 0) + pci_release_msi(dev); if (sc->sc_mem_res != NULL) { bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, @@ -1433,7 +1463,8 @@ et_chip_init(struct et_softc *sc) CSR_WRITE_4(sc, ET_LOOPBACK, 0); /* Clear MSI configure */ - CSR_WRITE_4(sc, ET_MSI_CFG, 0); + if ((sc->sc_flags & ET_FLAG_MSI) == 0) + CSR_WRITE_4(sc, ET_MSI_CFG, 0); /* Disable timer */ CSR_WRITE_4(sc, ET_TIMER, 0); |