diff options
author | Rahul Lakkireddy <rahul.lakkireddy@chelsio.com> | 2021-12-07 03:03:47 +0530 |
---|---|---|
committer | Robert Mustacchi <rm@fingolfin.org> | 2022-03-14 16:53:32 +0000 |
commit | 77ac03cbec412857d39c4898c9ed10abb6061418 (patch) | |
tree | bc2e6321ad8cf66c63dc0f231357bf58fbb1a0ec | |
parent | 311330e6823a3a919ff127757c2f0cf9eb17aa0e (diff) | |
download | illumos-joyent-77ac03cbec412857d39c4898c9ed10abb6061418.tar.gz |
14291 cxgbe: asserts when requesting more queues than available
Reviewed by: Igor Kozhukhov <igor@dilos.org>
Reviewed by: Ryan Zezeski <ryan@oxide.computer>
Approved by: Robert Mustacchi <rm@fingolfin.org>
-rw-r--r-- | usr/src/uts/common/io/cxgbe/common/common.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/io/cxgbe/common/t4_hw.c | 1 | ||||
-rw-r--r-- | usr/src/uts/common/io/cxgbe/t4nex/adapter.h | 6 | ||||
-rw-r--r-- | usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c | 226 | ||||
-rw-r--r-- | usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c | 20 |
5 files changed, 166 insertions, 88 deletions
diff --git a/usr/src/uts/common/io/cxgbe/common/common.h b/usr/src/uts/common/io/cxgbe/common/common.h index 76c7778f45..58235c0a05 100644 --- a/usr/src/uts/common/io/cxgbe/common/common.h +++ b/usr/src/uts/common/io/cxgbe/common/common.h @@ -333,7 +333,6 @@ struct pf_resources { unsigned int neq; /* N egress Qs */ unsigned int nethctrl; /* N egress ETH or CTRL Qs */ unsigned int niqflint; /* N ingress Qs/w free list(s) & intr */ - unsigned int niq; /* N ingress Qs */ unsigned int tc; /* PCI-E traffic class */ unsigned int pmask; /* port access rights mask */ unsigned int nexactf; /* N exact MPS filters */ diff --git a/usr/src/uts/common/io/cxgbe/common/t4_hw.c b/usr/src/uts/common/io/cxgbe/common/t4_hw.c index f83131720e..f22da3f5c7 100644 --- a/usr/src/uts/common/io/cxgbe/common/t4_hw.c +++ b/usr/src/uts/common/io/cxgbe/common/t4_hw.c @@ -3380,7 +3380,6 @@ int t4_get_pfres(struct adapter *adapter) */ word = be32_to_cpu(rpl.niqflint_niq); pfres->niqflint = G_FW_PFVF_CMD_NIQFLINT(word); - pfres->niq = G_FW_PFVF_CMD_NIQ(word); word = be32_to_cpu(rpl.type_to_neq); pfres->neq = G_FW_PFVF_CMD_NEQ(word); diff --git a/usr/src/uts/common/io/cxgbe/t4nex/adapter.h b/usr/src/uts/common/io/cxgbe/t4nex/adapter.h index 081fe870b1..32feb079e7 100644 --- a/usr/src/uts/common/io/cxgbe/t4nex/adapter.h +++ b/usr/src/uts/common/io/cxgbe/t4nex/adapter.h @@ -428,8 +428,10 @@ struct sge { struct sge_ofld_rxq *ofld_rxq; /* TOE rx queues */ #endif - uint16_t iq_start; - int eq_start; + int iq_start; /* iq context id map start index */ + int eq_start; /* eq context id map start index */ + int iqmap_sz; /* size of iq context id map */ + int eqmap_sz; /* size of eq context id map */ struct sge_iq **iqmap; /* iq->cntxt_id to iq mapping */ struct sge_eq **eqmap; /* eq->cntxt_id to eq mapping */ diff --git a/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c b/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c index 894950c2e7..9180de2392 100644 --- a/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c +++ b/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c @@ -303,7 +303,7 @@ t4_devo_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) struct adapter *sc = NULL; struct sge *s; int i, instance, rc = DDI_SUCCESS, rqidx, tqidx, q; - int irq = 0, nxg, n100g, n40g, n25g, n10g, n1g; + int irq = 0, nxg = 0, n1g = 0; #ifdef TCP_OFFLOAD_ENABLE int ofld_rqidx, ofld_tqidx; #endif @@ -525,7 +525,6 @@ t4_devo_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) * out whether a port is 10G or 1G and use that information when * calculating how many interrupts to attempt to allocate. */ - n100g = n40g = n25g = n10g = n1g = 0; for_each_port(sc, i) { struct port_info *pi; @@ -552,20 +551,8 @@ t4_devo_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) mutex_init(&pi->lock, NULL, MUTEX_DRIVER, NULL); pi->mtu = ETHERMTU; - if (is_100G_port(pi)) { - n100g++; - pi->tmr_idx = prp->tmr_idx_10g; - pi->pktc_idx = prp->pktc_idx_10g; - } else if (is_40G_port(pi)) { - n40g++; - pi->tmr_idx = prp->tmr_idx_10g; - pi->pktc_idx = prp->pktc_idx_10g; - } else if (is_25G_port(pi)) { - n25g++; - pi->tmr_idx = prp->tmr_idx_10g; - pi->pktc_idx = prp->pktc_idx_10g; - } else if (is_10G_port(pi)) { - n10g++; + if (is_10XG_port(pi)) { + nxg++; pi->tmr_idx = prp->tmr_idx_10g; pi->pktc_idx = prp->pktc_idx_10g; } else { @@ -580,7 +567,6 @@ t4_devo_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) setbit(&sc->registered_device_map, i); } - nxg = n10g + n25g + n40g + n100g; (void) remove_extra_props(sc, nxg, n1g); if (sc->registered_device_map == 0) { @@ -642,8 +628,8 @@ t4_devo_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) #endif s->rxq = kmem_zalloc(s->nrxq * sizeof (struct sge_rxq), KM_SLEEP); s->txq = kmem_zalloc(s->ntxq * sizeof (struct sge_txq), KM_SLEEP); - s->iqmap = kmem_zalloc(s->niq * sizeof (struct sge_iq *), KM_SLEEP); - s->eqmap = kmem_zalloc(s->neq * sizeof (struct sge_eq *), KM_SLEEP); + s->iqmap = kmem_zalloc(s->iqmap_sz * sizeof (struct sge_iq *), KM_SLEEP); + s->eqmap = kmem_zalloc(s->eqmap_sz * sizeof (struct sge_eq *), KM_SLEEP); sc->intr_handle = kmem_zalloc(sc->intr_count * sizeof (ddi_intr_handle_t), KM_SLEEP); @@ -815,46 +801,12 @@ ofld_queues: */ t4_dump_version_info(sc); - if (n100g) { - cxgb_printf(dip, CE_NOTE, - "%dx100G (%d rxq, %d txq total) %d %s.", - n100g, rqidx, tqidx, sc->intr_count, - sc->intr_type == DDI_INTR_TYPE_MSIX ? "MSI-X interrupts" : - sc->intr_type == DDI_INTR_TYPE_MSI ? "MSI interrupts" : - "fixed interrupt"); - } else if (n40g) { - cxgb_printf(dip, CE_NOTE, - "%dx40G (%d rxq, %d txq total) %d %s.", - n40g, rqidx, tqidx, sc->intr_count, - sc->intr_type == DDI_INTR_TYPE_MSIX ? "MSI-X interrupts" : - sc->intr_type == DDI_INTR_TYPE_MSI ? "MSI interrupts" : - "fixed interrupt"); - } else if (n25g) { - cxgb_printf(dip, CE_NOTE, - "%dx25G (%d rxq, %d txq total) %d %s.", - n25g, rqidx, tqidx, sc->intr_count, + cxgb_printf(dip, CE_NOTE, + "(%d rxq, %d txq total) %d %s.", + rqidx, tqidx, sc->intr_count, sc->intr_type == DDI_INTR_TYPE_MSIX ? "MSI-X interrupts" : sc->intr_type == DDI_INTR_TYPE_MSI ? "MSI interrupts" : "fixed interrupt"); - } else if (n10g && n1g) { - cxgb_printf(dip, CE_NOTE, - "%dx10G %dx1G (%d rxq, %d txq total) %d %s.", - n10g, n1g, rqidx, tqidx, sc->intr_count, - sc->intr_type == DDI_INTR_TYPE_MSIX ? "MSI-X interrupts" : - sc->intr_type == DDI_INTR_TYPE_MSI ? "MSI interrupts" : - "fixed interrupt"); - } else { - cxgb_printf(dip, CE_NOTE, - "%dx%sG (%d rxq, %d txq per port) %d %s.", - n10g ? n10g : n1g, - n10g ? "10" : "1", - n10g ? iaq.nrxq10g : iaq.nrxq1g, - n10g ? iaq.ntxq10g : iaq.ntxq1g, - sc->intr_count, - sc->intr_type == DDI_INTR_TYPE_MSIX ? "MSI-X interrupts" : - sc->intr_type == DDI_INTR_TYPE_MSI ? "MSI interrupts" : - "fixed interrupt"); - } sc->ksp = setup_kstats(sc); sc->ksp_stat = setup_wc_kstats(sc); @@ -934,9 +886,9 @@ t4_devo_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) if (s->txq != NULL) kmem_free(s->txq, s->ntxq * sizeof (struct sge_txq)); if (s->iqmap != NULL) - kmem_free(s->iqmap, s->niq * sizeof (struct sge_iq *)); + kmem_free(s->iqmap, s->iqmap_sz * sizeof (struct sge_iq *)); if (s->eqmap != NULL) - kmem_free(s->eqmap, s->neq * sizeof (struct sge_eq *)); + kmem_free(s->eqmap, s->eqmap_sz * sizeof (struct sge_eq *)); if (s->rxbuf_cache != NULL) rxbuf_cache_destroy(s->rxbuf_cache); @@ -1708,6 +1660,19 @@ get_params__post_init(struct adapter *sc) sc->vres.l2t.start = val[4]; sc->vres.l2t.size = val[5] - val[4] + 1; + param[0] = FW_PARAM_PFVF(IQFLINT_END); + param[1] = FW_PARAM_PFVF(EQ_END); + rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 2, param, val); + if (rc != 0) { + cxgb_printf(sc->dip, CE_WARN, + "failed to query eq/iq map size parameters (post_init): %d.\n", + rc); + return (rc); + } + + sc->sge.iqmap_sz = val[0] - sc->sge.iq_start + 1; + sc->sge.eqmap_sz = val[1] - sc->sge.eq_start + 1; + /* get capabilites */ bzero(&caps, sizeof (caps)); caps.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | @@ -1744,6 +1709,13 @@ get_params__post_init(struct adapter *sc) sc->params.offload = 1; } + rc = -t4_get_pfres(sc); + if (rc != 0) { + cxgb_printf(sc->dip, CE_WARN, + "failed to query PF resource params: %d.\n", rc); + return (rc); + } + /* These are finalized by FW initialization, load their values now */ val[0] = t4_read_reg(sc, A_TP_TIMER_RESOLUTION); sc->params.tp.tre = G_TIMERRESOLUTION(val[0]); @@ -2127,22 +2099,113 @@ cfg_itype_and_nqueues(struct adapter *sc, int n10g, int n1g, struct intrs_and_queues *iaq) { struct driver_properties *p = &sc->props; - int rc, itype, itypes, navail, nc, nrxq10g, nrxq1g, n; - int nofldrxq10g = 0, nofldrxq1g = 0; + int rc, itype, itypes, navail, nc, n; + int pfres_rxq, pfres_txq, pfresq; bzero(iaq, sizeof (*iaq)); nc = ncpus; /* our snapshot of the number of CPUs */ iaq->ntxq10g = min(nc, p->max_ntxq_10g); iaq->ntxq1g = min(nc, p->max_ntxq_1g); - iaq->nrxq10g = nrxq10g = min(nc, p->max_nrxq_10g); - iaq->nrxq1g = nrxq1g = min(nc, p->max_nrxq_1g); + iaq->nrxq10g = min(nc, p->max_nrxq_10g); + iaq->nrxq1g = min(nc, p->max_nrxq_1g); #ifdef TCP_OFFLOAD_ENABLE iaq->nofldtxq10g = min(nc, p->max_nofldtxq_10g); iaq->nofldtxq1g = min(nc, p->max_nofldtxq_1g); - iaq->nofldrxq10g = nofldrxq10g = min(nc, p->max_nofldrxq_10g); - iaq->nofldrxq1g = nofldrxq1g = min(nc, p->max_nofldrxq_1g); + iaq->nofldrxq10g = min(nc, p->max_nofldrxq_10g); + iaq->nofldrxq1g = min(nc, p->max_nofldrxq_1g); +#endif + + pfres_rxq = iaq->nrxq10g * n10g + iaq->nrxq1g * n1g; + pfres_txq = iaq->ntxq10g * n10g + iaq->ntxq1g * n1g; +#ifdef TCP_OFFLOAD_ENABLE + pfres_rxq += iaq->nofldrxq10g * n10g + iaq->nofldrxq1g * n1g; + pfres_txq += iaq->nofldtxq10g * n10g + iaq->nofldtxq1g * n1g; +#endif + + /* If current configuration of max number of Rxqs and Txqs exceed + * the max available for all the ports under this PF, then shrink + * the queues to max available. Reduce them in a way that each + * port under this PF has equally distributed number of queues. + * Must guarantee at least 1 queue for each port for both NIC + * and Offload queues. + * + * neq - fixed max number of Egress queues on Tx path and Free List + * queues that hold Rx payload data on Rx path. Half are reserved + * for Egress queues and the other half for Free List queues. + * Hence, the division by 2. + * + * niqflint - max number of Ingress queues with interrupts on Rx + * path to receive completions that indicate Rx payload has been + * posted in its associated Free List queue. Also handles Tx + * completions for packets successfully transmitted on Tx path. + * + * nethctrl - max number of Egress queues only for Tx path. This + * number is usually half of neq. However, if it became less than + * neq due to lack of resources based on firmware configuration, + * then take the lower value. + */ + while (pfres_rxq > + min(sc->params.pfres.neq / 2, sc->params.pfres.niqflint)) { + pfresq = pfres_rxq; + + if (iaq->nrxq10g > 1) { + iaq->nrxq10g--; + pfres_rxq -= n10g; + } + + if (iaq->nrxq1g > 1) { + iaq->nrxq1g--; + pfres_rxq -= n1g; + } + +#ifdef TCP_OFFLOAD_ENABLE + if (iaq->nofldrxq10g > 1) { + iaq->nofldrxq10g--; + pfres_rxq -= n10g; + } + + if (iaq->nofldrxq1g > 1) { + iaq->nofldrxq1g--; + pfres_rxq -= n1g; + } #endif + /* Break if nothing changed */ + if (pfresq == pfres_rxq) + break; + } + + while (pfres_txq > + min(sc->params.pfres.neq / 2, sc->params.pfres.nethctrl)) { + pfresq = pfres_txq; + + if (iaq->ntxq10g > 1) { + iaq->ntxq10g--; + pfres_txq -= n10g; + } + + if (iaq->ntxq1g > 1) { + iaq->ntxq1g--; + pfres_txq -= n1g; + } + +#ifdef TCP_OFFLOAD_ENABLE + if (iaq->nofldtxq10g > 1) { + iaq->nofldtxq10g--; + pfres_txq -= n10g; + } + + if (iaq->nofldtxq1g > 1) { + iaq->nofldtxq1g--; + pfres_txq -= n1g; + } +#endif + + /* Break if nothing changed */ + if (pfresq == pfres_txq) + break; + } + rc = ddi_intr_get_supported_types(sc->dip, &itypes); if (rc != DDI_SUCCESS) { cxgb_printf(sc->dip, CE_WARN, @@ -2177,8 +2240,12 @@ cfg_itype_and_nqueues(struct adapter *sc, int n10g, int n1g, * as offload). */ iaq->nirq = T4_EXTRA_INTR; - iaq->nirq += n10g * (nrxq10g + nofldrxq10g); - iaq->nirq += n1g * (nrxq1g + nofldrxq1g); + iaq->nirq += n10g * iaq->nrxq10g; + iaq->nirq += n1g * iaq->nrxq1g; +#ifdef TCP_OFFLOAD_ENABLE + iaq->nirq += n10g * iaq->nofldrxq10g; + iaq->nirq += n1g * iaq->nofldrxq1g; +#endif if (iaq->nirq <= navail && (itype != DDI_INTR_TYPE_MSI || ISP2(iaq->nirq))) { @@ -2192,8 +2259,13 @@ cfg_itype_and_nqueues(struct adapter *sc, int n10g, int n1g, * offload rxq's. */ iaq->nirq = T4_EXTRA_INTR; - iaq->nirq += n10g * max(nrxq10g, nofldrxq10g); - iaq->nirq += n1g * max(nrxq1g, nofldrxq1g); +#ifdef TCP_OFFLOAD_ENABLE + iaq->nirq += n10g * max(iaq->nrxq10g, iaq->nofldrxq10g); + iaq->nirq += n1g * max(iaq->nrxq1g, iaq->nofldrxq1g); +#else + iaq->nirq += n10g * iaq->nrxq10g; + iaq->nirq += n1g * iaq->nrxq1g; +#endif if (iaq->nirq <= navail && (itype != DDI_INTR_TYPE_MSI || ISP2(iaq->nirq))) { iaq->intr_fwd = 1; @@ -2212,32 +2284,38 @@ cfg_itype_and_nqueues(struct adapter *sc, int n10g, int n1g, int leftover = navail - iaq->nirq; if (n10g > 0) { - int target = max(nrxq10g, nofldrxq10g); + int target = iaq->nrxq10g; +#ifdef TCP_OFFLOAD_ENABLE + target = max(target, iaq->nofldrxq10g); +#endif n = 1; while (n < target && leftover >= n10g) { leftover -= n10g; iaq->nirq += n10g; n++; } - iaq->nrxq10g = min(n, nrxq10g); + iaq->nrxq10g = min(n, iaq->nrxq10g); #ifdef TCP_OFFLOAD_ENABLE - iaq->nofldrxq10g = min(n, nofldrxq10g); + iaq->nofldrxq10g = min(n, iaq->nofldrxq10g); #endif } if (n1g > 0) { - int target = max(nrxq1g, nofldrxq1g); + int target = iaq->nrxq1g; +#ifdef TCP_OFFLOAD_ENABLE + target = max(target, iaq->nofldrxq1g); +#endif n = 1; while (n < target && leftover >= n1g) { leftover -= n1g; iaq->nirq += n1g; n++; } - iaq->nrxq1g = min(n, nrxq1g); + iaq->nrxq1g = min(n, iaq->nrxq1g); #ifdef TCP_OFFLOAD_ENABLE - iaq->nofldrxq1g = min(n, nofldrxq1g); + iaq->nofldrxq1g = min(n, iaq->nofldrxq1g); #endif } diff --git a/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c b/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c index 3ec695dfbe..1560206373 100644 --- a/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c +++ b/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c @@ -1425,9 +1425,9 @@ alloc_iq_fl(struct port_info *pi, struct sge_iq *iq, struct sge_fl *fl, iq->polling = 0; cntxt_id = iq->cntxt_id - sc->sge.iq_start; - if (cntxt_id >= sc->sge.niq) { + if (cntxt_id >= sc->sge.iqmap_sz) { panic("%s: iq->cntxt_id (%d) more than the max (%d)", __func__, - cntxt_id, sc->sge.niq - 1); + cntxt_id, sc->sge.iqmap_sz - 1); } sc->sge.iqmap[cntxt_id] = iq; @@ -1437,9 +1437,9 @@ alloc_iq_fl(struct port_info *pi, struct sge_iq *iq, struct sge_fl *fl, fl->copy_threshold = rx_copy_threshold; cntxt_id = fl->cntxt_id - sc->sge.eq_start; - if (cntxt_id >= sc->sge.neq) { + if (cntxt_id >= sc->sge.eqmap_sz) { panic("%s: fl->cntxt_id (%d) more than the max (%d)", - __func__, cntxt_id, sc->sge.neq - 1); + __func__, cntxt_id, sc->sge.eqmap_sz - 1); } sc->sge.eqmap[cntxt_id] = (void *)fl; @@ -1685,9 +1685,9 @@ ctrl_eq_alloc(struct adapter *sc, struct sge_eq *eq) eq->cntxt_id = G_FW_EQ_CTRL_CMD_EQID(BE_32(c.cmpliqid_eqid)); cntxt_id = eq->cntxt_id - sc->sge.eq_start; - if (cntxt_id >= sc->sge.neq) + if (cntxt_id >= sc->sge.eqmap_sz) panic("%s: eq->cntxt_id (%d) more than the max (%d)", __func__, - cntxt_id, sc->sge.neq - 1); + cntxt_id, sc->sge.eqmap_sz - 1); sc->sge.eqmap[cntxt_id] = eq; return (rc); @@ -1728,9 +1728,9 @@ eth_eq_alloc(struct adapter *sc, struct port_info *pi, struct sge_eq *eq) eq->cntxt_id = G_FW_EQ_ETH_CMD_EQID(BE_32(c.eqid_pkd)); cntxt_id = eq->cntxt_id - sc->sge.eq_start; - if (cntxt_id >= sc->sge.neq) + if (cntxt_id >= sc->sge.eqmap_sz) panic("%s: eq->cntxt_id (%d) more than the max (%d)", __func__, - cntxt_id, sc->sge.neq - 1); + cntxt_id, sc->sge.eqmap_sz - 1); sc->sge.eqmap[cntxt_id] = eq; return (rc); @@ -1771,9 +1771,9 @@ ofld_eq_alloc(struct adapter *sc, struct port_info *pi, struct sge_eq *eq) eq->cntxt_id = G_FW_EQ_OFLD_CMD_EQID(BE_32(c.eqid_pkd)); cntxt_id = eq->cntxt_id - sc->sge.eq_start; - if (cntxt_id >= sc->sge.neq) + if (cntxt_id >= sc->sge.eqmap_sz) panic("%s: eq->cntxt_id (%d) more than the max (%d)", __func__, - cntxt_id, sc->sge.neq - 1); + cntxt_id, sc->sge.eqmap_sz - 1); sc->sge.eqmap[cntxt_id] = eq; return (rc); |