From patchwork Thu Dec 21 18:05:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ajit Khaparde X-Patchwork-Id: 135482 X-Patchwork-Delegate: ajit.khaparde@broadcom.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id D6A6143752; Thu, 21 Dec 2023 19:06:37 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4686B42EC4; Thu, 21 Dec 2023 19:05:48 +0100 (CET) Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) by mails.dpdk.org (Postfix) with ESMTP id 7009742E9E for ; Thu, 21 Dec 2023 19:05:45 +0100 (CET) Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-1d04c097e34so8035405ad.0 for ; Thu, 21 Dec 2023 10:05:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1703181944; x=1703786744; darn=dpdk.org; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=YddV6JzjyB2l1hKlMCgBNjI9dWf95KTA0f56wSF9fmY=; b=IMJbsHmsmGLc2SNy8p6UGtkgea5fMRuueYypauPvG3Z/Gg2JcXS0I0a9Y3QIOLZV5k jn2Nju1gCOCqOlY4Nlg/eO1PTOdGRB1EaYEK928Po7CAwdh+pac6J3NaqJSsPLrxztgR diQh901R+6nGayr5JpIavfVfDC0Gf5IJWv+PA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703181944; x=1703786744; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=YddV6JzjyB2l1hKlMCgBNjI9dWf95KTA0f56wSF9fmY=; b=olxQ23HTUWcI+sLTqc6lyCvkk2baJnmR/coXO0Xi1M+VQwF5u5e0SYx8cwhVeAelO7 w9Ij5fLHdrurNTKAxVwvu3cAJfKvK2VOah7PpAIq+Um3PH+eRU0Mr0P92BLsjDSQ7PgW vbba1/yGtiNT4PhDfiA/zhQjwhrOrcKSZAWOZx2rceinykzuowckzJjWKVXDTbn2H6b7 1POQZELKesHBNOtU3roVhAXyZ+SBxHftt4RuJwWZiPDlHx2mCrs+i5aWlhZQ5jwHNeK3 qLG9MXRISTuQIXIDQIvKH03I9buf9mu/va4sd+8yxtwopZmJEjITySBG2aO73pFhr2nF WyIw== X-Gm-Message-State: AOJu0YwhKLUT+nKmvkp7itqJwwDdza6ss1MWR9OphwihSRWTMjd2ynAU 8TNYygbFRZWZAObZvLJ2oF55Z97ze7sWRcyfuTFQ8t0hlm5kBfDJbffPVFbLbdNnHxXZ8YuUern XWIM5mAZLwavRbvEmxESfJwsyrgipDH/xwxjVm6IbkTDmJ0NqLT9PnwY1uhzOtSbk3x7qSJc+vR 0= X-Google-Smtp-Source: AGHT+IEVKHlOxXB9/cIhfsKBZn5yiHj0y5XQC4CRryyl56kTnJxCE8NBR3kNgZiASGhgLgiPvJivkg== X-Received: by 2002:a17:902:7209:b0:1d3:f783:5133 with SMTP id ba9-20020a170902720900b001d3f7835133mr1143432plb.0.1703181943797; Thu, 21 Dec 2023 10:05:43 -0800 (PST) Received: from C02GC2QQMD6T.wifi.broadcom.net ([192.19.223.252]) by smtp.gmail.com with ESMTPSA id j17-20020a170902da9100b001d3b3ac2d7bsm1916379plx.245.2023.12.21.10.05.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Dec 2023 10:05:43 -0800 (PST) From: Ajit Khaparde To: dev@dpdk.org Cc: Somnath Kotur Subject: [PATCH 07/18] net/bnxt: reattempt mbuf allocation for Rx and AGG rings Date: Thu, 21 Dec 2023 10:05:18 -0800 Message-Id: <20231221180529.18687-8-ajit.khaparde@broadcom.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20231221180529.18687-1-ajit.khaparde@broadcom.com> References: <20231221180529.18687-1-ajit.khaparde@broadcom.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Normally the PMD allocates a new mbuf for every mbuf consumed. In case of mbuf alloc failure, that slot in the Rx or AGG ring remains empty till a new mbuf is not allocated for that slot. If this happens too frequently the Rx ring or the aggregation ring could be completely drained of mbufs and can cause unexpected behavior. To prevent this, in case of an mbuf allocation failure, set a bit and try to reattempt mbuf allocation to fill the empty slots. Since this should not happen under normal circumstances, it should not impact regular Rx performance. The need_realloc bit is set in the RxQ if mbuf allocation fails for Rx ring or the AGG ring. As long as the application calls the Rx burst function even in cases where the Rx rings became completely empty, the logic should be able to reattempt buffer allocation for the associated Rx and aggregation rings. Signed-off-by: Ajit Khaparde Reviewed-by: Somnath Kotur --- drivers/net/bnxt/bnxt_rxq.h | 1 + drivers/net/bnxt/bnxt_rxr.c | 101 ++++++++++++++++++++++-------------- 2 files changed, 64 insertions(+), 38 deletions(-) diff --git a/drivers/net/bnxt/bnxt_rxq.h b/drivers/net/bnxt/bnxt_rxq.h index b9908be5f4..77bc382a1d 100644 --- a/drivers/net/bnxt/bnxt_rxq.h +++ b/drivers/net/bnxt/bnxt_rxq.h @@ -41,6 +41,7 @@ struct bnxt_rx_queue { struct bnxt_cp_ring_info *cp_ring; struct rte_mbuf fake_mbuf; uint64_t rx_mbuf_alloc_fail; + uint8_t need_realloc; const struct rte_memzone *mz; }; diff --git a/drivers/net/bnxt/bnxt_rxr.c b/drivers/net/bnxt/bnxt_rxr.c index b919922a64..c5c9f9e6e6 100644 --- a/drivers/net/bnxt/bnxt_rxr.c +++ b/drivers/net/bnxt/bnxt_rxr.c @@ -50,6 +50,8 @@ static inline int bnxt_alloc_rx_data(struct bnxt_rx_queue *rxq, mbuf = __bnxt_alloc_rx_data(rxq->mb_pool); if (!mbuf) { __atomic_fetch_add(&rxq->rx_mbuf_alloc_fail, 1, __ATOMIC_RELAXED); + /* If buff has failed already, setting this again won't hurt */ + rxq->need_realloc = 1; return -ENOMEM; } @@ -85,6 +87,8 @@ static inline int bnxt_alloc_ag_data(struct bnxt_rx_queue *rxq, mbuf = __bnxt_alloc_rx_data(rxq->mb_pool); if (!mbuf) { __atomic_fetch_add(&rxq->rx_mbuf_alloc_fail, 1, __ATOMIC_RELAXED); + /* If buff has failed already, setting this again won't hurt */ + rxq->need_realloc = 1; return -ENOMEM; } @@ -139,7 +143,6 @@ static void bnxt_rx_ring_reset(void *arg) int i, rc = 0; struct bnxt_rx_queue *rxq; - for (i = 0; i < (int)bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr; @@ -357,7 +360,8 @@ static int bnxt_rx_pages(struct bnxt_rx_queue *rxq, RTE_ASSERT(ag_cons <= rxr->ag_ring_struct->ring_mask); ag_buf = &rxr->ag_buf_ring[ag_cons]; ag_mbuf = *ag_buf; - RTE_ASSERT(ag_mbuf != NULL); + if (ag_mbuf == NULL) + return -EBUSY; ag_mbuf->data_len = rte_le_to_cpu_16(rxcmp->len); @@ -452,7 +456,7 @@ static inline struct rte_mbuf *bnxt_tpa_end( RTE_ASSERT(mbuf != NULL); if (agg_bufs) { - bnxt_rx_pages(rxq, mbuf, raw_cp_cons, agg_bufs, tpa_info); + (void)bnxt_rx_pages(rxq, mbuf, raw_cp_cons, agg_bufs, tpa_info); } mbuf->l4_len = payload_offset; @@ -1230,8 +1234,11 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt, bnxt_set_mark_in_mbuf(rxq->bp, rxcmp1, mbuf); reuse_rx_mbuf: - if (agg_buf) - bnxt_rx_pages(rxq, mbuf, &tmp_raw_cons, agg_buf, NULL); + if (agg_buf) { + rc = bnxt_rx_pages(rxq, mbuf, &tmp_raw_cons, agg_buf, NULL); + if (rc != 0) + return -EBUSY; + } #ifdef BNXT_DEBUG if (rxcmp1->errors_v2 & RX_CMP_L2_ERRORS) { @@ -1293,6 +1300,48 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt, return rc; } +static void bnxt_reattempt_buffer_alloc(struct bnxt_rx_queue *rxq) +{ + struct bnxt_rx_ring_info *rxr = rxq->rx_ring; + struct bnxt_ring *ring; + uint16_t raw_prod; + uint32_t cnt; + + /* Assume alloc passes. On failure, + * need_realloc will be set inside bnxt_alloc_XY_data. + */ + rxq->need_realloc = 0; + if (!bnxt_need_agg_ring(rxq->bp->eth_dev)) + goto alloc_rx; + + raw_prod = rxr->ag_raw_prod; + bnxt_prod_ag_mbuf(rxq); + if (raw_prod != rxr->ag_raw_prod) + bnxt_db_write(&rxr->ag_db, rxr->ag_raw_prod); + +alloc_rx: + raw_prod = rxr->rx_raw_prod; + ring = rxr->rx_ring_struct; + for (cnt = 0; cnt < ring->ring_size; cnt++) { + struct rte_mbuf **rx_buf; + uint16_t ndx; + + ndx = RING_IDX(ring, raw_prod + cnt); + rx_buf = &rxr->rx_buf_ring[ndx]; + + /* Buffer already allocated for this index. */ + if (*rx_buf != NULL && *rx_buf != &rxq->fake_mbuf) + continue; + + /* This slot is empty. Alloc buffer for Rx */ + if (bnxt_alloc_rx_data(rxq, rxr, raw_prod + cnt)) + break; + + rxr->rx_raw_prod = raw_prod + cnt; + bnxt_db_write(&rxr->rx_db, rxr->rx_raw_prod); + } +} + uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { @@ -1302,7 +1351,6 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t rx_raw_prod = rxr->rx_raw_prod; uint16_t ag_raw_prod = rxr->ag_raw_prod; uint32_t raw_cons = cpr->cp_raw_cons; - bool alloc_failed = false; uint32_t cons; int nb_rx_pkts = 0; int nb_rep_rx_pkts = 0; @@ -1358,10 +1406,8 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, break; else if (rc == -ENODEV) /* completion for representor */ nb_rep_rx_pkts++; - else if (rc == -ENOMEM) { + else if (rc == -ENOMEM) nb_rx_pkts++; - alloc_failed = true; - } } else if (!BNXT_NUM_ASYNC_CPR(rxq->bp)) { evt = bnxt_event_hwrm_resp_handler(rxq->bp, @@ -1372,7 +1418,12 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, } raw_cons = NEXT_RAW_CMP(raw_cons); - if (nb_rx_pkts == nb_pkts || nb_rep_rx_pkts == nb_pkts || evt) + /* + * The HW reposting may fall behind if mbuf allocation has + * failed. Break and reattempt allocation to prevent that. + */ + if (nb_rx_pkts == nb_pkts || nb_rep_rx_pkts == nb_pkts || evt || + rxq->need_realloc != 0) break; } @@ -1395,35 +1446,9 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, /* Ring the AGG ring DB */ if (ag_raw_prod != rxr->ag_raw_prod) bnxt_db_write(&rxr->ag_db, rxr->ag_raw_prod); - - /* Attempt to alloc Rx buf in case of a previous allocation failure. */ - if (alloc_failed) { - int cnt; - - rx_raw_prod = RING_NEXT(rx_raw_prod); - for (cnt = 0; cnt < nb_rx_pkts + nb_rep_rx_pkts; cnt++) { - struct rte_mbuf **rx_buf; - uint16_t ndx; - - ndx = RING_IDX(rxr->rx_ring_struct, rx_raw_prod + cnt); - rx_buf = &rxr->rx_buf_ring[ndx]; - - /* Buffer already allocated for this index. */ - if (*rx_buf != NULL && *rx_buf != &rxq->fake_mbuf) - continue; - - /* This slot is empty. Alloc buffer for Rx */ - if (!bnxt_alloc_rx_data(rxq, rxr, rx_raw_prod + cnt)) { - rxr->rx_raw_prod = rx_raw_prod + cnt; - bnxt_db_write(&rxr->rx_db, rxr->rx_raw_prod); - } else { - PMD_DRV_LOG(ERR, "Alloc mbuf failed\n"); - break; - } - } - } - done: + if (unlikely(rxq->need_realloc)) + bnxt_reattempt_buffer_alloc(rxq); return nb_rx_pkts; }