From b59ce7750ef65b548c4e3449bb59750f075aadb6 Mon Sep 17 00:00:00 2001 From: jmatthew Date: Fri, 23 Apr 2021 07:00:58 +0000 Subject: [PATCH] When we have a single tx/rx queue, the cp ring is also used for async events, so it can't be allocated when the interface is brought up and freed when it's taken down. ok dlg@ --- sys/dev/pci/if_bnxt.c | 67 ++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/sys/dev/pci/if_bnxt.c b/sys/dev/pci/if_bnxt.c index ac9cc4a510d..931d02ccda7 100644 --- a/sys/dev/pci/if_bnxt.c +++ b/sys/dev/pci/if_bnxt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bnxt.c,v 1.30 2021/04/23 04:58:34 jmatthew Exp $ */ +/* $OpenBSD: if_bnxt.c,v 1.31 2021/04/23 07:00:58 jmatthew Exp $ */ /*- * Broadcom NetXtreme-C/E network driver. * @@ -730,32 +730,35 @@ bnxt_queue_up(struct bnxt_softc *sc, struct bnxt_queue *bq) goto free_tx; } - cp->ring_mem = bnxt_dmamem_alloc(sc, PAGE_SIZE * BNXT_CP_PAGES); - if (cp->ring_mem == NULL) { - printf("%s: failed to allocate completion ring %d mem\n", - DEVNAME(sc), bq->q_index); - goto free_rx; - } - cp->ring.vaddr = BNXT_DMA_KVA(cp->ring_mem); - cp->ring.paddr = BNXT_DMA_DVA(cp->ring_mem); - cp->cons = UINT32_MAX; - cp->v_bit = 1; - bnxt_mark_cpr_invalid(cp); - - if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, - &cp->ring, (uint16_t)HWRM_NA_SIGNATURE, - HWRM_NA_SIGNATURE, 1) != 0) { - printf("%s: failed to allocate completion queue %d\n", - DEVNAME(sc), bq->q_index); - goto free_rx; - } + /* completion ring is already allocated if we only have one queue */ + if (sc->sc_nqueues > 1) { + cp->ring_mem = bnxt_dmamem_alloc(sc, PAGE_SIZE * BNXT_CP_PAGES); + if (cp->ring_mem == NULL) { + printf("%s: failed to allocate completion ring %d mem\n", + DEVNAME(sc), bq->q_index); + goto free_rx; + } + cp->ring.vaddr = BNXT_DMA_KVA(cp->ring_mem); + cp->ring.paddr = BNXT_DMA_DVA(cp->ring_mem); + cp->cons = UINT32_MAX; + cp->v_bit = 1; + bnxt_mark_cpr_invalid(cp); + + if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, + &cp->ring, (uint16_t)HWRM_NA_SIGNATURE, + HWRM_NA_SIGNATURE, 1) != 0) { + printf("%s: failed to allocate completion queue %d\n", + DEVNAME(sc), bq->q_index); + goto free_rx; + } - if (bnxt_set_cp_ring_aggint(sc, cp) != 0) { - printf("%s: failed to set interrupt %d aggregation\n", - DEVNAME(sc), bq->q_index); - goto free_rx; + if (bnxt_set_cp_ring_aggint(sc, cp) != 0) { + printf("%s: failed to set interrupt %d aggregation\n", + DEVNAME(sc), bq->q_index); + goto free_rx; + } + bnxt_write_cp_doorbell(sc, &cp->ring, 1); } - bnxt_write_cp_doorbell(sc, &cp->ring, 1); if (bnxt_hwrm_stat_ctx_alloc(sc, &bq->q_cp, BNXT_DMA_DVA(sc->sc_stats_ctx_mem) + @@ -960,17 +963,21 @@ bnxt_queue_down(struct bnxt_softc *sc, struct bnxt_queue *bq) &rx->rx_ag_ring); bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, &rx->rx_ring); - bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, - &cp->ring); + + /* if only one queue, leave cp ring in place for async events */ + if (sc->sc_nqueues > 1) { + bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, + &cp->ring); + + bnxt_dmamem_free(sc, cp->ring_mem); + cp->ring_mem = NULL; + } bnxt_dmamem_free(sc, rx->rx_ring_mem); rx->rx_ring_mem = NULL; bnxt_dmamem_free(sc, tx->tx_ring_mem); tx->tx_ring_mem = NULL; - - bnxt_dmamem_free(sc, cp->ring_mem); - cp->ring_mem = NULL; } void -- 2.20.1