diff options
author | John Levon <john.levon@joyent.com> | 2018-11-20 20:12:56 +0000 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2018-11-25 21:18:12 -0500 |
commit | bbb9d5d65bf8372aae4b8821c80e218b8b832846 (patch) | |
tree | 3f6c9dae60323284d282389414ee442bc258a39b | |
parent | 4450d42479b62d9a48049d644ff47b97009d9da2 (diff) | |
download | illumos-gate-bbb9d5d65bf8372aae4b8821c80e218b8b832846.tar.gz |
9994 cxgbe t4nex: Handle get_fl_payload() alloc failures
9995 cxgbe t4_devo_attach() should initialize ->sfl
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r-- | usr/src/uts/common/io/cxgbe/t4nex/adapter.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c | 1 | ||||
-rw-r--r-- | usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c | 57 |
3 files changed, 45 insertions, 14 deletions
diff --git a/usr/src/uts/common/io/cxgbe/t4nex/adapter.h b/usr/src/uts/common/io/cxgbe/t4nex/adapter.h index f66b707071..14f4fc9d75 100644 --- a/usr/src/uts/common/io/cxgbe/t4nex/adapter.h +++ b/usr/src/uts/common/io/cxgbe/t4nex/adapter.h @@ -281,6 +281,7 @@ struct sge_fl { uint64_t copied_up; /* # of frames copied into mblk and handed up */ uint64_t passed_up; /* # of frames wrapped in mblk and handed up */ + uint64_t allocb_fail; /* # of mblk allocation failures */ TAILQ_ENTRY(sge_fl) link; /* All starving freelists */ }; 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 6e396a1c0c..ec590228b6 100644 --- a/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c +++ b/usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c @@ -317,6 +317,7 @@ t4_devo_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) mutex_init(&sc->lock, NULL, MUTEX_DRIVER, NULL); cv_init(&sc->cv, NULL, CV_DRIVER, NULL); mutex_init(&sc->sfl_lock, NULL, MUTEX_DRIVER, NULL); + TAILQ_INIT(&sc->sfl); mutex_enter(&t4_adapter_list_lock); SLIST_INSERT_HEAD(&t4_adapter_list, sc, link); 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 2c808a23fe..ce0ac3dbe3 100644 --- a/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c +++ b/usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c @@ -775,10 +775,8 @@ t4_ring_rx(struct sge_rxq *rxq, int budget) goto done; m = get_fl_payload(sc, fl, lq, &fl_bufs_used); - if (m == NULL) { - panic("%s: line %d.", __func__, - __LINE__); - } + if (m == NULL) + goto done; iq->intr_next = iq->intr_params; m->b_rptr += sc->sge.pktshift; @@ -808,10 +806,8 @@ t4_ring_rx(struct sge_rxq *rxq, int budget) } m = get_fl_payload(sc, fl, lq, &fl_bufs_used); - if (m == NULL) { - panic("%s: line %d.", __func__, - __LINE__); - } + if (m == NULL) + goto done; /* FALLTHROUGH */ case X_RSPD_TYPE_CPL: @@ -861,6 +857,7 @@ service_iq(struct sge_iq *iq, int budget) int ndescs = 0, limit, fl_bufs_used = 0; int rsp_type; uint32_t lq; + int starved; mblk_t *m; STAILQ_HEAD(, sge_iq) iql = STAILQ_HEAD_INITIALIZER(iql); @@ -887,8 +884,23 @@ service_iq(struct sge_iq *iq, int budget) m = get_fl_payload(sc, fl, lq, &fl_bufs_used); if (m == NULL) { - panic("%s: line %d.", __func__, - __LINE__); + /* + * Rearm the iq with a + * longer-than-default timer + */ + t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), V_CIDXINC(ndescs) | + V_INGRESSQID((u32)iq->cntxt_id) | + V_SEINTARM(V_QINTR_TIMER_IDX(SGE_NTIMERS-1))); + if (fl_bufs_used > 0) { + ASSERT(iq->flags & IQ_HAS_FL); + FL_LOCK(fl); + fl->needed += fl_bufs_used; + starved = refill_fl(sc, fl, fl->cap / 8); + FL_UNLOCK(fl); + if (starved) + add_fl_to_sfl(sc, fl); + } + return (0); } /* FALLTHRU */ @@ -968,7 +980,6 @@ service_iq(struct sge_iq *iq, int budget) V_INGRESSQID((u32)iq->cntxt_id) | V_SEINTARM(iq->intr_next)); if (iq->flags & IQ_HAS_FL) { - int starved; FL_LOCK(fl); fl->needed += fl_bufs_used; @@ -1253,6 +1264,7 @@ init_fl(struct sge_fl *fl, uint16_t qsize) { fl->qsize = qsize; + fl->allocb_fail = 0; } static inline void @@ -2331,13 +2343,15 @@ get_fl_payload(struct adapter *sc, struct sge_fl *fl, struct rxbuf *rxb; mblk_t *m = NULL; uint_t nbuf = 0, len, copy, n; - uint32_t cidx, offset; + uint32_t cidx, offset, rcidx, roffset; /* * The SGE won't pack a new frame into the current buffer if the entire * payload doesn't fit in the remaining space. Move on to the next buf * in that case. */ + rcidx = fl->cidx; + roffset = fl->offset; if (fl->offset > 0 && len_newbuf & F_RSPD_NEWBUF) { fl->offset = 0; if (++fl->cidx == fl->cap) @@ -2351,8 +2365,15 @@ get_fl_payload(struct adapter *sc, struct sge_fl *fl, copy = (len <= fl->copy_threshold); if (copy != 0) { frame.head = m = allocb(len, BPRI_HI); - if (m == NULL) + if (m == NULL) { + fl->allocb_fail++; + cmn_err(CE_WARN,"%s: mbuf allocation failure " + "count = %llu", __func__, + (unsigned long long)fl->allocb_fail); + fl->cidx = rcidx; + fl->offset = roffset; return (NULL); + } } while (len) { @@ -2368,7 +2389,15 @@ get_fl_payload(struct adapter *sc, struct sge_fl *fl, m = desballoc((unsigned char *)rxb->va + offset, n, BPRI_HI, &rxb->freefunc); if (m == NULL) { - freemsg(frame.head); + fl->allocb_fail++; + cmn_err(CE_WARN, + "%s: mbuf allocation failure " + "count = %llu", __func__, + (unsigned long long)fl->allocb_fail); + if (frame.head) + freemsgchain(frame.head); + fl->cidx = rcidx; + fl->offset = roffset; return (NULL); } atomic_inc_uint(&rxb->ref_cnt); |