Print this page
9994 cxgbe t4nex: Handle get_fl_payload() alloc failures
9995 cxgbe t4_devo_attach() should initialize ->sfl
@@ -773,14 +773,12 @@
if (iq->polling && ((received_bytes + pkt_len) > 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;
if (sc->params.tp.rx_pkt_encap)
/* It is enabled only in T6 config file */
@@ -806,14 +804,12 @@
break;
}
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:
ASSERT(rss->opcode < NUM_CPL_CMDS);
sc->cpl_handler[rss->opcode](iq, rss, m);
@@ -859,10 +855,11 @@
struct rsp_ctrl *ctrl;
const struct rss_header *rss;
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);
limit = budget ? budget : iq->qsize / 8;
@@ -885,13 +882,28 @@
ASSERT(iq->flags & IQ_HAS_FL);
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 */
case X_RSPD_TYPE_CPL:
ASSERT(rss->opcode < NUM_CPL_CMDS);
@@ -966,11 +978,10 @@
t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), V_CIDXINC(ndescs) |
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;
starved = refill_fl(sc, fl, fl->cap / 4);
FL_UNLOCK(fl);
@@ -1251,10 +1262,11 @@
static inline void
init_fl(struct sge_fl *fl, uint16_t qsize)
{
fl->qsize = qsize;
+ fl->allocb_fail = 0;
}
static inline void
init_eq(struct adapter *sc, struct sge_eq *eq, uint16_t eqtype, uint16_t qsize,
uint8_t tx_chan, uint16_t iqid)
@@ -2329,17 +2341,19 @@
{
struct mblk_pair frame = {0};
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)
fl->cidx = 0;
nbuf++;
@@ -2349,13 +2363,20 @@
len = G_RSPD_LEN(len_newbuf); /* pktshift + payload length */
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) {
rxb = fl->sdesc[cidx].rxb;
n = min(len, rxb->buf_size - offset);
@@ -2366,11 +2387,19 @@
bcopy(rxb->va + offset, m->b_wptr, n);
else {
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);
if (frame.head != NULL)
frame.tail->b_cont = m;