Blame SOURCES/0001-net-qede-fix-MTU-set-and-max-Rx-length.patch

a6040a
From 9e334305178fd3715c17088632544bf58e5836a9 Mon Sep 17 00:00:00 2001
a6040a
From: Rasesh Mody <rasesh.mody@cavium.com>
a6040a
Date: Sat, 27 Jan 2018 13:15:30 -0800
a6040a
Subject: [PATCH] net/qede: fix MTU set and max Rx length
a6040a
a6040a
This patch fixes issues related to MTU set and max_rx_pkt_len usage.
a6040a
 - Adjust MTU during device configuration when jumbo is enabled
a6040a
a6040a
 - In qede_set_mtu():
a6040a
   Return not supported for VF as currently we do not support it.
a6040a
a6040a
   Cache new mtu value in mtu_new for proper update.
a6040a
a6040a
   Add check for RXQ allocation before calculating RX buffer size
a6040a
   if not allocated defer RX buffer size calculation till RXQ setup.
a6040a
a6040a
   Add check for before performing device start/stop.
a6040a
a6040a
 - Use max_rx_pkt_len appropriately
a6040a
a6040a
 - Change QEDE_ETH_OVERHEAD macro to adjust driver specifics
a6040a
a6040a
Fixes: 4c4bdadfa9e7 ("net/qede: refactoring multi-queue implementation")
a6040a
Fixes: 9a6d30ae6d46 ("net/qede: refactoring vport handling code")
a6040a
Fixes: 1ef4c3a5c1f7 ("net/qede: prevent crash while changing MTU dynamically")
a6040a
Cc: stable@dpdk.org
a6040a
a6040a
Signed-off-by: Rasesh Mody <rasesh.mody@cavium.com>
a6040a
---
a6040a
 drivers/net/qede/qede_ethdev.c | 63 ++++++++++++++++++++++++++++--------------
a6040a
 drivers/net/qede/qede_rxtx.c   |  6 ++--
a6040a
 drivers/net/qede/qede_rxtx.h   |  2 +-
a6040a
 3 files changed, 47 insertions(+), 24 deletions(-)
a6040a
a6040a
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
a6040a
index 323e8ed3b..895a0da61 100644
a6040a
--- a/drivers/net/qede/qede_ethdev.c
a6040a
+++ b/drivers/net/qede/qede_ethdev.c
a6040a
@@ -1414,18 +1414,24 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
a6040a
 			return -ENOMEM;
a6040a
 	}
a6040a
 
a6040a
+	/* If jumbo enabled adjust MTU */
a6040a
+	if (eth_dev->data->dev_conf.rxmode.jumbo_frame)
a6040a
+		eth_dev->data->mtu =
a6040a
+				eth_dev->data->dev_conf.rxmode.max_rx_pkt_len -
a6040a
+				ETHER_HDR_LEN - ETHER_CRC_LEN;
a6040a
+
a6040a
 	/* VF's MTU has to be set using vport-start where as
a6040a
 	 * PF's MTU can be updated via vport-update.
a6040a
 	 */
a6040a
 	if (IS_VF(edev)) {
a6040a
-		if (qede_start_vport(qdev, rxmode->max_rx_pkt_len))
a6040a
+		if (qede_start_vport(qdev, eth_dev->data->mtu))
a6040a
 			return -1;
a6040a
 	} else {
a6040a
-		if (qede_update_mtu(eth_dev, rxmode->max_rx_pkt_len))
a6040a
+		if (qede_update_mtu(eth_dev, eth_dev->data->mtu))
a6040a
 			return -1;
a6040a
 	}
a6040a
 
a6040a
-	qdev->mtu = rxmode->max_rx_pkt_len;
a6040a
+	qdev->mtu = eth_dev->data->mtu;
a6040a
 	qdev->new_mtu = qdev->mtu;
a6040a
 
a6040a
 	/* Enable VLAN offloads by default */
a6040a
@@ -2306,16 +2312,23 @@ static int qede_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
a6040a
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
a6040a
 	struct rte_eth_dev_info dev_info = {0};
a6040a
 	struct qede_fastpath *fp;
a6040a
+	uint32_t max_rx_pkt_len;
a6040a
 	uint32_t frame_size;
a6040a
 	uint16_t rx_buf_size;
a6040a
 	uint16_t bufsz;
a6040a
+	bool restart = false;
a6040a
 	int i;
a6040a
 
a6040a
 	PMD_INIT_FUNC_TRACE(edev);
a6040a
+	if (IS_VF(edev))
a6040a
+		return -ENOTSUP;
a6040a
 	qede_dev_info_get(dev, &dev_info);
a6040a
-	frame_size = mtu + QEDE_ETH_OVERHEAD;
a6040a
+	max_rx_pkt_len = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
a6040a
+	frame_size = max_rx_pkt_len + QEDE_ETH_OVERHEAD;
a6040a
 	if ((mtu < ETHER_MIN_MTU) || (frame_size > dev_info.max_rx_pktlen)) {
a6040a
-		DP_ERR(edev, "MTU %u out of range\n", mtu);
a6040a
+		DP_ERR(edev, "MTU %u out of range, %u is maximum allowable\n",
a6040a
+		       mtu, dev_info.max_rx_pktlen - ETHER_HDR_LEN -
a6040a
+			ETHER_CRC_LEN - QEDE_ETH_OVERHEAD);
a6040a
 		return -EINVAL;
a6040a
 	}
a6040a
 	if (!dev->data->scattered_rx &&
a6040a
@@ -2329,29 +2342,39 @@ static int qede_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
a6040a
 	 */
a6040a
 	dev->rx_pkt_burst = qede_rxtx_pkts_dummy;
a6040a
 	dev->tx_pkt_burst = qede_rxtx_pkts_dummy;
a6040a
-	qede_dev_stop(dev);
a6040a
+	if (dev->data->dev_started) {
a6040a
+		dev->data->dev_started = 0;
a6040a
+		qede_dev_stop(dev);
a6040a
+		restart = true;
a6040a
+	}
a6040a
 	rte_delay_ms(1000);
a6040a
-	qdev->mtu = mtu;
a6040a
+	qdev->new_mtu = mtu;
a6040a
 	/* Fix up RX buf size for all queues of the port */
a6040a
 	for_each_rss(i) {
a6040a
 		fp = &qdev->fp_array[i];
a6040a
-		bufsz = (uint16_t)rte_pktmbuf_data_room_size(
a6040a
-			fp->rxq->mb_pool) - RTE_PKTMBUF_HEADROOM;
a6040a
-		if (dev->data->scattered_rx)
a6040a
-			rx_buf_size = bufsz + QEDE_ETH_OVERHEAD;
a6040a
-		else
a6040a
-			rx_buf_size = mtu + QEDE_ETH_OVERHEAD;
a6040a
-		rx_buf_size = QEDE_CEIL_TO_CACHE_LINE_SIZE(rx_buf_size);
a6040a
-		fp->rxq->rx_buf_size = rx_buf_size;
a6040a
-		DP_INFO(edev, "buf_size adjusted to %u\n", rx_buf_size);
a6040a
-	}
a6040a
-	qede_dev_start(dev);
a6040a
-	if (frame_size > ETHER_MAX_LEN)
a6040a
+		if (fp->rxq != NULL) {
a6040a
+			bufsz = (uint16_t)rte_pktmbuf_data_room_size(
a6040a
+				fp->rxq->mb_pool) - RTE_PKTMBUF_HEADROOM;
a6040a
+			if (dev->data->scattered_rx)
a6040a
+				rx_buf_size = bufsz + ETHER_HDR_LEN +
a6040a
+					      ETHER_CRC_LEN + QEDE_ETH_OVERHEAD;
a6040a
+			else
a6040a
+				rx_buf_size = frame_size;
a6040a
+			rx_buf_size = QEDE_CEIL_TO_CACHE_LINE_SIZE(rx_buf_size);
a6040a
+			fp->rxq->rx_buf_size = rx_buf_size;
a6040a
+			DP_INFO(edev, "buf_size adjusted to %u\n", rx_buf_size);
a6040a
+		}
a6040a
+	}
a6040a
+	if (max_rx_pkt_len > ETHER_MAX_LEN)
a6040a
 		dev->data->dev_conf.rxmode.jumbo_frame = 1;
a6040a
 	else
a6040a
 		dev->data->dev_conf.rxmode.jumbo_frame = 0;
a6040a
+	if (!dev->data->dev_started && restart) {
a6040a
+		qede_dev_start(dev);
a6040a
+		dev->data->dev_started = 1;
a6040a
+	}
a6040a
 	/* update max frame size */
a6040a
-	dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
a6040a
+	dev->data->dev_conf.rxmode.max_rx_pkt_len = max_rx_pkt_len;
a6040a
 	/* Reassign back */
a6040a
 	dev->rx_pkt_burst = qede_recv_pkts;
a6040a
 	dev->tx_pkt_burst = qede_xmit_pkts;
a6040a
diff --git a/drivers/net/qede/qede_rxtx.c b/drivers/net/qede/qede_rxtx.c
a6040a
index df248cf7e..810f0f394 100644
a6040a
--- a/drivers/net/qede/qede_rxtx.c
a6040a
+++ b/drivers/net/qede/qede_rxtx.c
a6040a
@@ -84,7 +84,6 @@ qede_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
a6040a
 	rxq->port_id = dev->data->port_id;
a6040a
 
a6040a
 	max_rx_pkt_len = (uint16_t)rxmode->max_rx_pkt_len;
a6040a
-	qdev->mtu = max_rx_pkt_len;
a6040a
 
a6040a
 	/* Fix up RX buffer size */
a6040a
 	bufsz = (uint16_t)rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM;
a6040a
@@ -97,9 +96,10 @@ qede_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
a6040a
 	}
a6040a
 
a6040a
 	if (dev->data->scattered_rx)
a6040a
-		rxq->rx_buf_size = bufsz + QEDE_ETH_OVERHEAD;
a6040a
+		rxq->rx_buf_size = bufsz + ETHER_HDR_LEN +
a6040a
+				   ETHER_CRC_LEN + QEDE_ETH_OVERHEAD;
a6040a
 	else
a6040a
-		rxq->rx_buf_size = qdev->mtu + QEDE_ETH_OVERHEAD;
a6040a
+		rxq->rx_buf_size = max_rx_pkt_len + QEDE_ETH_OVERHEAD;
a6040a
 	/* Align to cache-line size if needed */
a6040a
 	rxq->rx_buf_size = QEDE_CEIL_TO_CACHE_LINE_SIZE(rxq->rx_buf_size);
a6040a
 
a6040a
diff --git a/drivers/net/qede/qede_rxtx.h b/drivers/net/qede/qede_rxtx.h
a6040a
index 6214c97f3..f1d366613 100644
a6040a
--- a/drivers/net/qede/qede_rxtx.h
a6040a
+++ b/drivers/net/qede/qede_rxtx.h
a6040a
@@ -64,7 +64,7 @@
a6040a
 #define QEDE_CEIL_TO_CACHE_LINE_SIZE(n) (((n) + (QEDE_FW_RX_ALIGN_END - 1)) & \
a6040a
 					~(QEDE_FW_RX_ALIGN_END - 1))
a6040a
 /* Note: QEDE_LLC_SNAP_HDR_LEN is optional */
a6040a
-#define QEDE_ETH_OVERHEAD	((ETHER_HDR_LEN) + ((2 * QEDE_VLAN_TAG_SIZE)) \
a6040a
+#define QEDE_ETH_OVERHEAD	(((2 * QEDE_VLAN_TAG_SIZE)) - (ETHER_CRC_LEN) \
a6040a
 				+ (QEDE_LLC_SNAP_HDR_LEN))
a6040a
 
a6040a
 #define QEDE_RSS_OFFLOAD_ALL    (ETH_RSS_IPV4			|\
a6040a
-- 
a6040a
2.14.3
a6040a