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;