summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2018-11-20 20:12:56 +0000
committerDan McDonald <danmcd@joyent.com>2018-11-25 21:18:12 -0500
commitbbb9d5d65bf8372aae4b8821c80e218b8b832846 (patch)
tree3f6c9dae60323284d282389414ee442bc258a39b
parent4450d42479b62d9a48049d644ff47b97009d9da2 (diff)
downloadillumos-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.h1
-rw-r--r--usr/src/uts/common/io/cxgbe/t4nex/t4_nexus.c1
-rw-r--r--usr/src/uts/common/io/cxgbe/t4nex/t4_sge.c57
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);