[v2,4/4] net/bnxt: fix rxq start/stop for Thor based NICs
diff mbox series

Message ID 20191104230225.98450-5-ajit.khaparde@broadcom.com
State Accepted, archived
Delegated to: Ajit Khaparde
Headers show
Series
  • net/bnxt: rxq stop/start fixes
Related show

Checks

Context Check Description
ci/travis-robot success Travis build: passed
ci/Intel-compilation fail apply issues
ci/checkpatch success coding style OK

Commit Message

Ajit Khaparde Nov. 4, 2019, 11:02 p.m. UTC
From: Lance Richardson <lance.richardson@broadcom.com>

Controller-specific handling is required for Thor-based NICs when
stopping or starting a receive queue, otherwise packet reception
may not be reliably resumed when a stopped receive queue is
restarted:
  - The VNIC default receive ring needs to be recomputed when a
    receive queue is stopped or started.
  - When stopping the last (or only) receive queue for a given
    VNIC, ensure that no packets can reach the default receive
    ring by temporarily setting the VNIC MRU to zero.

Fixes: f8168ca0e690 ("net/bnxt: support thor controller")
Cc: stable@dpdk.org

Signed-off-by: Lance Richardson <lance.richardson@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
 drivers/net/bnxt/bnxt_hwrm.c | 27 +++++++++++++++++++++----
 drivers/net/bnxt/bnxt_rxq.c  | 38 +++++++++++++++++++++++++++++++++---
 2 files changed, 58 insertions(+), 7 deletions(-)

Patch
diff mbox series

diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index bb4dcf4b2..2cba007ea 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -1696,10 +1696,29 @@  int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 	HWRM_PREP(req, VNIC_CFG, BNXT_USE_CHIMP_MB);
 
 	if (BNXT_CHIP_THOR(bp)) {
-		struct bnxt_rx_queue *rxq =
-			bp->eth_dev->data->rx_queues[vnic->start_grp_id];
-		struct bnxt_rx_ring_info *rxr = rxq->rx_ring;
-		struct bnxt_cp_ring_info *cpr = rxq->cp_ring;
+		int dflt_rxq = vnic->start_grp_id;
+		struct bnxt_rx_ring_info *rxr;
+		struct bnxt_cp_ring_info *cpr;
+		struct bnxt_rx_queue *rxq;
+		int i;
+
+		/*
+		 * The first active receive ring is used as the VNIC
+		 * default receive ring. If there are no active receive
+		 * rings (all corresponding receive queues are stopped),
+		 * the first receive ring is used.
+		 */
+		for (i = vnic->start_grp_id; i < vnic->end_grp_id; i++) {
+			rxq = bp->eth_dev->data->rx_queues[i];
+			if (rxq->rx_started) {
+				dflt_rxq = i;
+				break;
+			}
+		}
+
+		rxq = bp->eth_dev->data->rx_queues[dflt_rxq];
+		rxr = rxq->rx_ring;
+		cpr = rxq->cp_ring;
 
 		req.default_rx_ring_id =
 			rte_cpu_to_le_16(rxr->rx_ring_struct->fw_ring_id);
diff --git a/drivers/net/bnxt/bnxt_rxq.c b/drivers/net/bnxt/bnxt_rxq.c
index e82eda9d7..e7c012f68 100644
--- a/drivers/net/bnxt/bnxt_rxq.c
+++ b/drivers/net/bnxt/bnxt_rxq.c
@@ -451,6 +451,10 @@  int bnxt_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 	if (rc)
 		return rc;
 
+	if (BNXT_CHIP_THOR(bp)) {
+		/* Reconfigure default receive ring and MRU. */
+		bnxt_hwrm_vnic_cfg(bp, rxq->vnic);
+	}
 	PMD_DRV_LOG(INFO, "Rx queue started %d\n", rx_queue_id);
 
 	if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) {
@@ -491,7 +495,8 @@  int bnxt_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
 	struct bnxt_vnic_info *vnic = NULL;
 	struct bnxt_rx_queue *rxq = NULL;
-	int rc = 0;
+	int active_queue_cnt = 0;
+	int i, rc = 0;
 
 	rc = is_bnxt_in_error(bp);
 	if (rc)
@@ -507,8 +512,9 @@  int bnxt_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 	}
 
 	rxq = bp->rx_queues[rx_queue_id];
+	vnic = rxq->vnic;
 
-	if (rxq == NULL) {
+	if (!rxq || !vnic) {
 		PMD_DRV_LOG(ERR, "Invalid Rx queue %d\n", rx_queue_id);
 		return -EINVAL;
 	}
@@ -518,7 +524,6 @@  int bnxt_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 	PMD_DRV_LOG(DEBUG, "Rx queue stopped\n");
 
 	if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) {
-		vnic = rxq->vnic;
 		if (BNXT_HAS_RING_GRPS(bp))
 			vnic->fw_grp_ids[rx_queue_id] = INVALID_HW_RING_ID;
 
@@ -526,6 +531,33 @@  int bnxt_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 		rc = bnxt_vnic_rss_configure(bp, vnic);
 	}
 
+	if (BNXT_CHIP_THOR(bp)) {
+		/* Compute current number of active receive queues. */
+		for (i = vnic->start_grp_id; i < vnic->end_grp_id; i++)
+			if (bp->rx_queues[i]->rx_started)
+				active_queue_cnt++;
+
+		/*
+		 * For Thor, we need to ensure that the VNIC default receive
+		 * ring corresponds to an active receive queue. When no queue
+		 * is active, we need to temporarily set the MRU to zero so
+		 * that packets are dropped early in the receive pipeline in
+		 * order to prevent the VNIC default receive ring from being
+		 * accessed.
+		 */
+		if (active_queue_cnt == 0) {
+			uint16_t saved_mru = vnic->mru;
+
+			vnic->mru = 0;
+			/* Reconfigure default receive ring and MRU. */
+			bnxt_hwrm_vnic_cfg(bp, vnic);
+			vnic->mru = saved_mru;
+		} else {
+			/* Reconfigure default receive ring. */
+			bnxt_hwrm_vnic_cfg(bp, vnic);
+		}
+	}
+
 	if (rc == 0)
 		bnxt_rx_queue_release_mbufs(rxq);