1227569Sphilip/*- 2301388Sarybchik * Copyright (c) 2010-2016 Solarflare Communications Inc. 3227569Sphilip * All rights reserved. 4227569Sphilip * 5227569Sphilip * This software was developed in part by Philip Paeps under contract for 6227569Sphilip * Solarflare Communications, Inc. 7227569Sphilip * 8227569Sphilip * Redistribution and use in source and binary forms, with or without 9284555Sarybchik * modification, are permitted provided that the following conditions are met: 10227569Sphilip * 11284555Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 12284555Sarybchik * this list of conditions and the following disclaimer. 13284555Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 14284555Sarybchik * this list of conditions and the following disclaimer in the documentation 15284555Sarybchik * and/or other materials provided with the distribution. 16284555Sarybchik * 17284555Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18284555Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19284555Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20284555Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21284555Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22284555Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23284555Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24284555Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25284555Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26284555Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 27284555Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28284555Sarybchik * 29284555Sarybchik * The views and conclusions contained in the software and documentation are 30284555Sarybchik * those of the authors and should not be interpreted as representing official 31284555Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 32227569Sphilip */ 33227569Sphilip 34227569Sphilip#include <sys/cdefs.h> 35227569Sphilip__FBSDID("$FreeBSD$"); 36227569Sphilip 37227569Sphilip#include <sys/param.h> 38227569Sphilip#include <sys/bus.h> 39227569Sphilip#include <sys/rman.h> 40227569Sphilip#include <sys/syslog.h> 41227569Sphilip 42227569Sphilip#include <machine/bus.h> 43227569Sphilip#include <machine/resource.h> 44227569Sphilip 45227569Sphilip#include <dev/pci/pcireg.h> 46227569Sphilip#include <dev/pci/pcivar.h> 47227569Sphilip 48227569Sphilip#include "common/efx.h" 49227569Sphilip 50227569Sphilip#include "sfxge.h" 51227569Sphilip 52227569Sphilipstatic int 53227569Sphilipsfxge_intr_line_filter(void *arg) 54227569Sphilip{ 55227569Sphilip struct sfxge_evq *evq; 56227569Sphilip struct sfxge_softc *sc; 57227569Sphilip efx_nic_t *enp; 58227569Sphilip struct sfxge_intr *intr; 59227569Sphilip boolean_t fatal; 60227569Sphilip uint32_t qmask; 61227569Sphilip 62227569Sphilip evq = (struct sfxge_evq *)arg; 63227569Sphilip sc = evq->sc; 64227569Sphilip enp = sc->enp; 65227569Sphilip intr = &sc->intr; 66227569Sphilip 67227569Sphilip KASSERT(intr != NULL, ("intr == NULL")); 68227569Sphilip KASSERT(intr->type == EFX_INTR_LINE, 69227569Sphilip ("intr->type != EFX_INTR_LINE")); 70227569Sphilip 71227700Sphilip if (intr->state != SFXGE_INTR_STARTED) 72280501Sarybchik return (FILTER_STRAY); 73227569Sphilip 74227569Sphilip (void)efx_intr_status_line(enp, &fatal, &qmask); 75227569Sphilip 76227569Sphilip if (fatal) { 77227569Sphilip (void) efx_intr_disable(enp); 78227569Sphilip (void) efx_intr_fatal(enp); 79280501Sarybchik return (FILTER_HANDLED); 80227569Sphilip } 81227569Sphilip 82227569Sphilip if (qmask != 0) { 83227569Sphilip intr->zero_count = 0; 84280501Sarybchik return (FILTER_SCHEDULE_THREAD); 85227569Sphilip } 86227569Sphilip 87227569Sphilip /* SF bug 15783: If the function is not asserting its IRQ and 88227569Sphilip * we read the queue mask on the cycle before a flag is added 89227569Sphilip * to the mask, this inhibits the function from asserting the 90227569Sphilip * IRQ even though we don't see the flag set. To work around 91227569Sphilip * this, we must re-prime all event queues and report the IRQ 92227569Sphilip * as handled when we see a mask of zero. To allow for shared 93227569Sphilip * IRQs, we don't repeat this if we see a mask of zero twice 94227569Sphilip * or more in a row. 95227569Sphilip */ 96227569Sphilip if (intr->zero_count++ == 0) { 97227569Sphilip if (evq->init_state == SFXGE_EVQ_STARTED) { 98227569Sphilip if (efx_ev_qpending(evq->common, evq->read_ptr)) 99280501Sarybchik return (FILTER_SCHEDULE_THREAD); 100227569Sphilip efx_ev_qprime(evq->common, evq->read_ptr); 101280501Sarybchik return (FILTER_HANDLED); 102227569Sphilip } 103227569Sphilip } 104227569Sphilip 105280501Sarybchik return (FILTER_STRAY); 106227569Sphilip} 107227569Sphilip 108227569Sphilipstatic void 109227569Sphilipsfxge_intr_line(void *arg) 110227569Sphilip{ 111227569Sphilip struct sfxge_evq *evq = arg; 112227569Sphilip 113280508Sarybchik (void)sfxge_ev_qpoll(evq); 114227569Sphilip} 115227569Sphilip 116227569Sphilipstatic void 117227569Sphilipsfxge_intr_message(void *arg) 118227569Sphilip{ 119227569Sphilip struct sfxge_evq *evq; 120227569Sphilip struct sfxge_softc *sc; 121227569Sphilip efx_nic_t *enp; 122227569Sphilip struct sfxge_intr *intr; 123227569Sphilip unsigned int index; 124227569Sphilip boolean_t fatal; 125227569Sphilip 126227569Sphilip evq = (struct sfxge_evq *)arg; 127227569Sphilip sc = evq->sc; 128227569Sphilip enp = sc->enp; 129227569Sphilip intr = &sc->intr; 130227569Sphilip index = evq->index; 131227569Sphilip 132227569Sphilip KASSERT(intr != NULL, ("intr == NULL")); 133227569Sphilip KASSERT(intr->type == EFX_INTR_MESSAGE, 134227569Sphilip ("intr->type != EFX_INTR_MESSAGE")); 135227569Sphilip 136280596Sarybchik if (__predict_false(intr->state != SFXGE_INTR_STARTED)) 137227569Sphilip return; 138227569Sphilip 139227569Sphilip (void)efx_intr_status_message(enp, index, &fatal); 140227569Sphilip 141227569Sphilip if (fatal) { 142227569Sphilip (void)efx_intr_disable(enp); 143227569Sphilip (void)efx_intr_fatal(enp); 144227569Sphilip return; 145227569Sphilip } 146227569Sphilip 147280508Sarybchik (void)sfxge_ev_qpoll(evq); 148227569Sphilip} 149227569Sphilip 150227569Sphilipstatic int 151227569Sphilipsfxge_intr_bus_enable(struct sfxge_softc *sc) 152227569Sphilip{ 153227569Sphilip struct sfxge_intr *intr; 154227569Sphilip struct sfxge_intr_hdl *table; 155227569Sphilip driver_filter_t *filter; 156227569Sphilip driver_intr_t *handler; 157227569Sphilip int index; 158227569Sphilip int err; 159227569Sphilip 160227569Sphilip intr = &sc->intr; 161227569Sphilip table = intr->table; 162227569Sphilip 163227569Sphilip switch (intr->type) { 164227569Sphilip case EFX_INTR_MESSAGE: 165227569Sphilip filter = NULL; /* not shared */ 166227569Sphilip handler = sfxge_intr_message; 167227569Sphilip break; 168227569Sphilip 169227569Sphilip case EFX_INTR_LINE: 170227569Sphilip filter = sfxge_intr_line_filter; 171227569Sphilip handler = sfxge_intr_line; 172227569Sphilip break; 173227569Sphilip 174227569Sphilip default: 175227569Sphilip KASSERT(0, ("Invalid interrupt type")); 176280501Sarybchik return (EINVAL); 177227569Sphilip } 178227569Sphilip 179227569Sphilip /* Try to add the handlers */ 180227569Sphilip for (index = 0; index < intr->n_alloc; index++) { 181227569Sphilip if ((err = bus_setup_intr(sc->dev, table[index].eih_res, 182227569Sphilip INTR_MPSAFE|INTR_TYPE_NET, filter, handler, 183227569Sphilip sc->evq[index], &table[index].eih_tag)) != 0) { 184227569Sphilip goto fail; 185227569Sphilip } 186227569Sphilip#ifdef SFXGE_HAVE_DESCRIBE_INTR 187227569Sphilip if (intr->n_alloc > 1) 188227569Sphilip bus_describe_intr(sc->dev, table[index].eih_res, 189227569Sphilip table[index].eih_tag, "%d", index); 190227569Sphilip#endif 191227569Sphilip bus_bind_intr(sc->dev, table[index].eih_res, index); 192227569Sphilip 193227569Sphilip } 194227569Sphilip 195227569Sphilip return (0); 196227569Sphilip 197227569Sphilipfail: 198227569Sphilip /* Remove remaining handlers */ 199227569Sphilip while (--index >= 0) 200227569Sphilip bus_teardown_intr(sc->dev, table[index].eih_res, 201227569Sphilip table[index].eih_tag); 202227569Sphilip 203227569Sphilip return (err); 204227569Sphilip} 205227569Sphilip 206227569Sphilipstatic void 207227569Sphilipsfxge_intr_bus_disable(struct sfxge_softc *sc) 208227569Sphilip{ 209227569Sphilip struct sfxge_intr *intr; 210227569Sphilip struct sfxge_intr_hdl *table; 211227569Sphilip int i; 212227569Sphilip 213227569Sphilip intr = &sc->intr; 214227569Sphilip table = intr->table; 215227569Sphilip 216227569Sphilip /* Remove all handlers */ 217227569Sphilip for (i = 0; i < intr->n_alloc; i++) 218227569Sphilip bus_teardown_intr(sc->dev, table[i].eih_res, 219227569Sphilip table[i].eih_tag); 220227569Sphilip} 221227569Sphilip 222227569Sphilipstatic int 223227569Sphilipsfxge_intr_alloc(struct sfxge_softc *sc, int count) 224227569Sphilip{ 225227569Sphilip device_t dev; 226227569Sphilip struct sfxge_intr_hdl *table; 227227569Sphilip struct sfxge_intr *intr; 228227569Sphilip struct resource *res; 229227569Sphilip int rid; 230227569Sphilip int error; 231227569Sphilip int i; 232227569Sphilip 233227569Sphilip dev = sc->dev; 234227569Sphilip intr = &sc->intr; 235227569Sphilip error = 0; 236227569Sphilip 237227569Sphilip table = malloc(count * sizeof(struct sfxge_intr_hdl), 238227569Sphilip M_SFXGE, M_WAITOK); 239227569Sphilip intr->table = table; 240227569Sphilip 241227569Sphilip for (i = 0; i < count; i++) { 242227569Sphilip rid = i + 1; 243227569Sphilip res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 244227569Sphilip RF_SHAREABLE | RF_ACTIVE); 245227569Sphilip if (res == NULL) { 246227569Sphilip device_printf(dev, "Couldn't allocate interrupts for " 247227569Sphilip "message %d\n", rid); 248227569Sphilip error = ENOMEM; 249227569Sphilip break; 250227569Sphilip } 251227569Sphilip table[i].eih_rid = rid; 252227569Sphilip table[i].eih_res = res; 253227569Sphilip } 254227569Sphilip 255280501Sarybchik if (error != 0) { 256227569Sphilip count = i - 1; 257227569Sphilip for (i = 0; i < count; i++) 258227569Sphilip bus_release_resource(dev, SYS_RES_IRQ, 259227569Sphilip table[i].eih_rid, table[i].eih_res); 260227569Sphilip } 261227569Sphilip 262227569Sphilip return (error); 263227569Sphilip} 264227569Sphilip 265227569Sphilipstatic void 266227569Sphilipsfxge_intr_teardown_msix(struct sfxge_softc *sc) 267227569Sphilip{ 268227569Sphilip device_t dev; 269227569Sphilip struct resource *resp; 270227569Sphilip int rid; 271227569Sphilip 272227569Sphilip dev = sc->dev; 273227569Sphilip resp = sc->intr.msix_res; 274227569Sphilip 275227569Sphilip rid = rman_get_rid(resp); 276227569Sphilip bus_release_resource(dev, SYS_RES_MEMORY, rid, resp); 277227569Sphilip} 278227569Sphilip 279227569Sphilipstatic int 280227569Sphilipsfxge_intr_setup_msix(struct sfxge_softc *sc) 281227569Sphilip{ 282227569Sphilip struct sfxge_intr *intr; 283227569Sphilip struct resource *resp; 284227569Sphilip device_t dev; 285227569Sphilip int count; 286227569Sphilip int rid; 287227569Sphilip 288227569Sphilip dev = sc->dev; 289227569Sphilip intr = &sc->intr; 290227569Sphilip 291227569Sphilip /* Check if MSI-X is available. */ 292227569Sphilip count = pci_msix_count(dev); 293227569Sphilip if (count == 0) 294227569Sphilip return (EINVAL); 295227569Sphilip 296284555Sarybchik /* Do not try to allocate more than already estimated EVQ maximum */ 297284555Sarybchik KASSERT(sc->evq_max > 0, ("evq_max is zero")); 298284555Sarybchik count = MIN(count, sc->evq_max); 299227569Sphilip 300227569Sphilip rid = PCIR_BAR(4); 301227569Sphilip resp = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 302227569Sphilip if (resp == NULL) 303227569Sphilip return (ENOMEM); 304227569Sphilip 305227569Sphilip if (pci_alloc_msix(dev, &count) != 0) { 306227569Sphilip bus_release_resource(dev, SYS_RES_MEMORY, rid, resp); 307227569Sphilip return (ENOMEM); 308227569Sphilip } 309227569Sphilip 310227569Sphilip /* Allocate interrupt handlers. */ 311227569Sphilip if (sfxge_intr_alloc(sc, count) != 0) { 312227569Sphilip bus_release_resource(dev, SYS_RES_MEMORY, rid, resp); 313227569Sphilip pci_release_msi(dev); 314227569Sphilip return (ENOMEM); 315227569Sphilip } 316227569Sphilip 317227569Sphilip intr->type = EFX_INTR_MESSAGE; 318227569Sphilip intr->n_alloc = count; 319227569Sphilip intr->msix_res = resp; 320227569Sphilip 321227569Sphilip return (0); 322227569Sphilip} 323227569Sphilip 324227569Sphilipstatic int 325227569Sphilipsfxge_intr_setup_msi(struct sfxge_softc *sc) 326227569Sphilip{ 327227569Sphilip struct sfxge_intr_hdl *table; 328227569Sphilip struct sfxge_intr *intr; 329227569Sphilip device_t dev; 330227569Sphilip int count; 331227569Sphilip int error; 332227569Sphilip 333227569Sphilip dev = sc->dev; 334227569Sphilip intr = &sc->intr; 335227569Sphilip table = intr->table; 336227569Sphilip 337227569Sphilip /* 338227569Sphilip * Check if MSI is available. All messages must be written to 339227569Sphilip * the same address and on x86 this means the IRQs have the 340227569Sphilip * same CPU affinity. So we only ever allocate 1. 341227569Sphilip */ 342227569Sphilip count = pci_msi_count(dev) ? 1 : 0; 343227569Sphilip if (count == 0) 344227569Sphilip return (EINVAL); 345227569Sphilip 346280501Sarybchik if ((error = pci_alloc_msi(dev, &count)) != 0) 347227569Sphilip return (ENOMEM); 348227569Sphilip 349227569Sphilip /* Allocate interrupt handler. */ 350227569Sphilip if (sfxge_intr_alloc(sc, count) != 0) { 351227569Sphilip pci_release_msi(dev); 352227569Sphilip return (ENOMEM); 353227569Sphilip } 354227569Sphilip 355227569Sphilip intr->type = EFX_INTR_MESSAGE; 356227569Sphilip intr->n_alloc = count; 357227569Sphilip 358227569Sphilip return (0); 359227569Sphilip} 360227569Sphilip 361227569Sphilipstatic int 362227569Sphilipsfxge_intr_setup_fixed(struct sfxge_softc *sc) 363227569Sphilip{ 364227569Sphilip struct sfxge_intr_hdl *table; 365227569Sphilip struct sfxge_intr *intr; 366227569Sphilip struct resource *res; 367227569Sphilip device_t dev; 368227569Sphilip int rid; 369227569Sphilip 370227569Sphilip dev = sc->dev; 371227569Sphilip intr = &sc->intr; 372227569Sphilip 373227569Sphilip rid = 0; 374227569Sphilip res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 375227569Sphilip RF_SHAREABLE | RF_ACTIVE); 376227569Sphilip if (res == NULL) 377227569Sphilip return (ENOMEM); 378227569Sphilip 379227569Sphilip table = malloc(sizeof(struct sfxge_intr_hdl), M_SFXGE, M_WAITOK); 380227569Sphilip table[0].eih_rid = rid; 381227569Sphilip table[0].eih_res = res; 382227569Sphilip 383227569Sphilip intr->type = EFX_INTR_LINE; 384227569Sphilip intr->n_alloc = 1; 385227569Sphilip intr->table = table; 386227569Sphilip 387227569Sphilip return (0); 388227569Sphilip} 389227569Sphilip 390227569Sphilipstatic const char *const __sfxge_err[] = { 391227569Sphilip "", 392227569Sphilip "SRAM out-of-bounds", 393227569Sphilip "Buffer ID out-of-bounds", 394227569Sphilip "Internal memory parity", 395227569Sphilip "Receive buffer ownership", 396227569Sphilip "Transmit buffer ownership", 397227569Sphilip "Receive descriptor ownership", 398227569Sphilip "Transmit descriptor ownership", 399227569Sphilip "Event queue ownership", 400227569Sphilip "Event queue FIFO overflow", 401227569Sphilip "Illegal address", 402227569Sphilip "SRAM parity" 403227569Sphilip}; 404227569Sphilip 405227569Sphilipvoid 406227569Sphilipsfxge_err(efsys_identifier_t *arg, unsigned int code, uint32_t dword0, 407284555Sarybchik uint32_t dword1) 408227569Sphilip{ 409227569Sphilip struct sfxge_softc *sc = (struct sfxge_softc *)arg; 410227569Sphilip device_t dev = sc->dev; 411227569Sphilip 412227569Sphilip log(LOG_WARNING, "[%s%d] FATAL ERROR: %s (0x%08x%08x)", 413227569Sphilip device_get_name(dev), device_get_unit(dev), 414227569Sphilip __sfxge_err[code], dword1, dword0); 415227569Sphilip} 416227569Sphilip 417227569Sphilipvoid 418227569Sphilipsfxge_intr_stop(struct sfxge_softc *sc) 419227569Sphilip{ 420227569Sphilip struct sfxge_intr *intr; 421280501Sarybchik 422227569Sphilip intr = &sc->intr; 423227569Sphilip 424227569Sphilip KASSERT(intr->state == SFXGE_INTR_STARTED, 425227569Sphilip ("Interrupts not started")); 426227569Sphilip 427227569Sphilip intr->state = SFXGE_INTR_INITIALIZED; 428227569Sphilip 429227569Sphilip /* Disable interrupts at the NIC */ 430227569Sphilip efx_intr_disable(sc->enp); 431227569Sphilip 432227569Sphilip /* Disable interrupts at the bus */ 433227569Sphilip sfxge_intr_bus_disable(sc); 434227569Sphilip 435227569Sphilip /* Tear down common code interrupt bits. */ 436227569Sphilip efx_intr_fini(sc->enp); 437227569Sphilip} 438227569Sphilip 439227569Sphilipint 440227569Sphilipsfxge_intr_start(struct sfxge_softc *sc) 441227569Sphilip{ 442227569Sphilip struct sfxge_intr *intr; 443227569Sphilip efsys_mem_t *esmp; 444227569Sphilip int rc; 445227569Sphilip 446227569Sphilip intr = &sc->intr; 447227569Sphilip esmp = &intr->status; 448227569Sphilip 449227569Sphilip KASSERT(intr->state == SFXGE_INTR_INITIALIZED, 450227569Sphilip ("Interrupts not initialized")); 451227569Sphilip 452227569Sphilip /* Zero the memory. */ 453227569Sphilip (void)memset(esmp->esm_base, 0, EFX_INTR_SIZE); 454227569Sphilip 455227569Sphilip /* Initialize common code interrupt bits. */ 456227569Sphilip (void)efx_intr_init(sc->enp, intr->type, esmp); 457227569Sphilip 458227569Sphilip /* Enable interrupts at the bus */ 459227569Sphilip if ((rc = sfxge_intr_bus_enable(sc)) != 0) 460227569Sphilip goto fail; 461227569Sphilip 462227700Sphilip intr->state = SFXGE_INTR_STARTED; 463227569Sphilip 464227569Sphilip /* Enable interrupts at the NIC */ 465227569Sphilip efx_intr_enable(sc->enp); 466227569Sphilip 467227569Sphilip return (0); 468227569Sphilip 469227569Sphilipfail: 470227569Sphilip /* Tear down common code interrupt bits. */ 471227569Sphilip efx_intr_fini(sc->enp); 472227569Sphilip 473227569Sphilip intr->state = SFXGE_INTR_INITIALIZED; 474227569Sphilip 475227569Sphilip return (rc); 476227569Sphilip} 477227569Sphilip 478227569Sphilipvoid 479227569Sphilipsfxge_intr_fini(struct sfxge_softc *sc) 480227569Sphilip{ 481227569Sphilip struct sfxge_intr_hdl *table; 482227569Sphilip struct sfxge_intr *intr; 483227569Sphilip efsys_mem_t *esmp; 484227569Sphilip device_t dev; 485227569Sphilip int i; 486227569Sphilip 487227569Sphilip dev = sc->dev; 488227569Sphilip intr = &sc->intr; 489227569Sphilip esmp = &intr->status; 490227569Sphilip table = intr->table; 491227569Sphilip 492227569Sphilip KASSERT(intr->state == SFXGE_INTR_INITIALIZED, 493227569Sphilip ("intr->state != SFXGE_INTR_INITIALIZED")); 494227569Sphilip 495227569Sphilip /* Free DMA memory. */ 496227569Sphilip sfxge_dma_free(esmp); 497227569Sphilip 498227569Sphilip /* Free interrupt handles. */ 499227569Sphilip for (i = 0; i < intr->n_alloc; i++) 500227569Sphilip bus_release_resource(dev, SYS_RES_IRQ, 501227569Sphilip table[i].eih_rid, table[i].eih_res); 502227569Sphilip 503227569Sphilip if (table[0].eih_rid != 0) 504227569Sphilip pci_release_msi(dev); 505227569Sphilip 506227569Sphilip if (intr->msix_res != NULL) 507227569Sphilip sfxge_intr_teardown_msix(sc); 508227569Sphilip 509227569Sphilip /* Free the handle table */ 510227569Sphilip free(table, M_SFXGE); 511227569Sphilip intr->table = NULL; 512227569Sphilip intr->n_alloc = 0; 513227569Sphilip 514227569Sphilip /* Clear the interrupt type */ 515227569Sphilip intr->type = EFX_INTR_INVALID; 516227569Sphilip 517227569Sphilip intr->state = SFXGE_INTR_UNINITIALIZED; 518227569Sphilip} 519227569Sphilip 520227569Sphilipint 521227569Sphilipsfxge_intr_init(struct sfxge_softc *sc) 522227569Sphilip{ 523227569Sphilip device_t dev; 524227569Sphilip struct sfxge_intr *intr; 525227569Sphilip efsys_mem_t *esmp; 526227569Sphilip int rc; 527227569Sphilip 528227569Sphilip dev = sc->dev; 529227569Sphilip intr = &sc->intr; 530227569Sphilip esmp = &intr->status; 531227569Sphilip 532227569Sphilip KASSERT(intr->state == SFXGE_INTR_UNINITIALIZED, 533227569Sphilip ("Interrupts already initialized")); 534227569Sphilip 535227569Sphilip /* Try to setup MSI-X or MSI interrupts if available. */ 536227569Sphilip if ((rc = sfxge_intr_setup_msix(sc)) == 0) 537227569Sphilip device_printf(dev, "Using MSI-X interrupts\n"); 538227569Sphilip else if ((rc = sfxge_intr_setup_msi(sc)) == 0) 539227569Sphilip device_printf(dev, "Using MSI interrupts\n"); 540227569Sphilip else if ((rc = sfxge_intr_setup_fixed(sc)) == 0) { 541227569Sphilip device_printf(dev, "Using fixed interrupts\n"); 542227569Sphilip } else { 543227569Sphilip device_printf(dev, "Couldn't setup interrupts\n"); 544227569Sphilip return (ENOMEM); 545227569Sphilip } 546227569Sphilip 547227569Sphilip /* Set up DMA for interrupts. */ 548227569Sphilip if ((rc = sfxge_dma_alloc(sc, EFX_INTR_SIZE, esmp)) != 0) 549227569Sphilip return (ENOMEM); 550227569Sphilip 551227569Sphilip intr->state = SFXGE_INTR_INITIALIZED; 552227569Sphilip 553227569Sphilip return (0); 554227569Sphilip} 555