diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 414624f31fb5..5b46e142519c 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -288,6 +288,7 @@ static int cxgbe_init_locked(struct port_info *); static int cxgbe_init_synchronized(struct port_info *); static int cxgbe_uninit_locked(struct port_info *); static int cxgbe_uninit_synchronized(struct port_info *); +static int setup_intr_handlers(struct adapter *); static int adapter_full_init(struct adapter *); static int adapter_full_uninit(struct adapter *); static int port_full_init(struct port_info *); @@ -701,6 +702,13 @@ t4_attach(device_t dev) #endif } + rc = setup_intr_handlers(sc); + if (rc != 0) { + device_printf(dev, + "failed to setup interrupt handlers: %d\n", rc); + goto done; + } + rc = bus_generic_attach(dev); if (rc != 0) { device_printf(dev, @@ -760,6 +768,9 @@ t4_detach(device_t dev) return (rc); } + for (i = 0; i < sc->intr_count; i++) + t4_free_irq(sc, &sc->irq[i]); + for (i = 0; i < MAX_NPORTS; i++) { pi = sc->port[i]; if (pi) { @@ -2360,16 +2371,14 @@ cxgbe_uninit_synchronized(struct port_info *pi) return (0); } -#define T4_ALLOC_IRQ(sc, irq, rid, handler, arg, name) do { \ - rc = t4_alloc_irq(sc, irq, rid, handler, arg, name); \ - if (rc != 0) \ - goto done; \ -} while (0) - +/* + * It is ok for this function to fail midway and return right away. t4_detach + * will walk the entire sc->irq list and clean up whatever is valid. + */ static int -adapter_full_init(struct adapter *sc) +setup_intr_handlers(struct adapter *sc) { - int rc, i, rid, p, q; + int rc, rid, p, q; char s[8]; struct irq *irq; struct port_info *pi; @@ -2378,30 +2387,6 @@ adapter_full_init(struct adapter *sc) struct sge_ofld_rxq *ofld_rxq; #endif - ADAPTER_LOCK_ASSERT_NOTOWNED(sc); - KASSERT((sc->flags & FULL_INIT_DONE) == 0, - ("%s: FULL_INIT_DONE already", __func__)); - - /* - * queues that belong to the adapter (not any particular port). - */ - rc = t4_setup_adapter_queues(sc); - if (rc != 0) - goto done; - - for (i = 0; i < nitems(sc->tq); i++) { - sc->tq[i] = taskqueue_create("t4 taskq", M_NOWAIT, - taskqueue_thread_enqueue, &sc->tq[i]); - if (sc->tq[i] == NULL) { - device_printf(sc->dev, - "failed to allocate task queue %d\n", i); - rc = ENOMEM; - goto done; - } - taskqueue_start_threads(&sc->tq[i], 1, PI_NET, "%s tq%d", - device_get_nameunit(sc->dev), i); - } - /* * Setup interrupts. */ @@ -2411,19 +2396,26 @@ adapter_full_init(struct adapter *sc) KASSERT(!(sc->flags & INTR_DIRECT), ("%s: single interrupt && INTR_DIRECT?", __func__)); - T4_ALLOC_IRQ(sc, irq, rid, t4_intr_all, sc, "all"); + rc = t4_alloc_irq(sc, irq, rid, t4_intr_all, sc, "all"); + if (rc != 0) + return (rc); } else { /* Multiple interrupts. */ KASSERT(sc->intr_count >= T4_EXTRA_INTR + sc->params.nports, ("%s: too few intr.", __func__)); /* The first one is always error intr */ - T4_ALLOC_IRQ(sc, irq, rid, t4_intr_err, sc, "err"); + rc = t4_alloc_irq(sc, irq, rid, t4_intr_err, sc, "err"); + if (rc != 0) + return (rc); irq++; rid++; /* The second one is always the firmware event queue */ - T4_ALLOC_IRQ(sc, irq, rid, t4_intr_evt, &sc->sge.fwq, "evt"); + rc = t4_alloc_irq(sc, irq, rid, t4_intr_evt, &sc->sge.fwq, + "evt"); + if (rc != 0) + return (rc); irq++; rid++; @@ -2450,7 +2442,10 @@ adapter_full_init(struct adapter *sc) rxq = &sc->sge.rxq[pi->first_rxq]; for (q = 0; q < pi->nrxq; q++, rxq++) { snprintf(s, sizeof(s), "%d.%d", p, q); - T4_ALLOC_IRQ(sc, irq, rid, t4_intr, rxq, s); + rc = t4_alloc_irq(sc, irq, rid, t4_intr, rxq, + s); + if (rc != 0) + return (rc); irq++; rid++; } @@ -2466,7 +2461,10 @@ adapter_full_init(struct adapter *sc) ofld_rxq = &sc->sge.ofld_rxq[pi->first_ofld_rxq]; for (q = 0; q < pi->nofldrxq; q++, ofld_rxq++) { snprintf(s, sizeof(s), "%d,%d", p, q); - T4_ALLOC_IRQ(sc, irq, rid, t4_intr, ofld_rxq, s); + rc = t4_alloc_irq(sc, irq, rid, t4_intr, + ofld_rxq, s); + if (rc != 0) + return (rc); irq++; rid++; } @@ -2474,6 +2472,38 @@ adapter_full_init(struct adapter *sc) } } + return (0); +} + +static int +adapter_full_init(struct adapter *sc) +{ + int rc, i; + + ADAPTER_LOCK_ASSERT_NOTOWNED(sc); + KASSERT((sc->flags & FULL_INIT_DONE) == 0, + ("%s: FULL_INIT_DONE already", __func__)); + + /* + * queues that belong to the adapter (not any particular port). + */ + rc = t4_setup_adapter_queues(sc); + if (rc != 0) + goto done; + + for (i = 0; i < nitems(sc->tq); i++) { + sc->tq[i] = taskqueue_create("t4 taskq", M_NOWAIT, + taskqueue_thread_enqueue, &sc->tq[i]); + if (sc->tq[i] == NULL) { + device_printf(sc->dev, + "failed to allocate task queue %d\n", i); + rc = ENOMEM; + goto done; + } + taskqueue_start_threads(&sc->tq[i], 1, PI_NET, "%s tq%d", + device_get_nameunit(sc->dev), i); + } + t4_intr_enable(sc); sc->flags |= FULL_INIT_DONE; done: @@ -2482,7 +2512,6 @@ adapter_full_init(struct adapter *sc) return (rc); } -#undef T4_ALLOC_IRQ static int adapter_full_uninit(struct adapter *sc) @@ -2493,9 +2522,6 @@ adapter_full_uninit(struct adapter *sc) t4_teardown_adapter_queues(sc); - for (i = 0; i < sc->intr_count; i++) - t4_free_irq(sc, &sc->irq[i]); - for (i = 0; i < nitems(sc->tq) && sc->tq[i]; i++) { taskqueue_free(sc->tq[i]); sc->tq[i] = NULL;