From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <luca.boccassi@gmail.com>
Received: from mail-wr0-f195.google.com (mail-wr0-f195.google.com
 [209.85.128.195]) by dpdk.org (Postfix) with ESMTP id 5EEF21DB9
 for <stable@dpdk.org>; Mon, 30 Apr 2018 16:07:53 +0200 (CEST)
Received: by mail-wr0-f195.google.com with SMTP id 94-v6so6853720wrf.5
 for <stable@dpdk.org>; Mon, 30 Apr 2018 07:07:53 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;
 h=from:to:cc:subject:date:message-id:in-reply-to:references;
 bh=U1PTNv4oTVgTdZSzE3WzBivgpW1OP6b/9WY5bK9COqc=;
 b=TbPatS6jC2YsoWfLygpVUoOiggERp1UKW3nWm1QvejBf8SKk6/j7LEZCEEjnyHFQT7
 sFcN5joqkzCQ7UQGB0ctqjCgHUIR0uxWPwLWUHWyY++OHjSp5aoOhauc6SJ0XZLg+9ap
 xK9RHPBnIyW4DDDL7xpJqjz/FXX81xBMFExfrhHIQpjWSnIHjgCtVmtgjxIgvbUjW6oL
 If6vBO7TRfiVBEU6aKM3M7PkNrpO3RyfLDvq4IQ7fgM4Gemj+pO8lrumSMIPcfTU7V/0
 VjYhXlPM3Bv/ERAYf3L5TgYBZoYsfXgO9QsPcKnM2yVxgvAvLnGkyvlSU+juXaOldm6Y
 8rmg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20161025;
 h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
 :references;
 bh=U1PTNv4oTVgTdZSzE3WzBivgpW1OP6b/9WY5bK9COqc=;
 b=uYxAR/pQcrvH3HVZ7A8ZGGpJz27RiBgdtvL7qdvIkl204IA5WBrtoQh/JS1Vi+FvF7
 Vh04/7+UIh0aPE0DeFFnL1GRzu66G2U0T+wnvQseemavWadMDVVZmS0AehDfTKeIef1P
 CY3EG11aekH3xsDXYdkWNr8nW6WZmwXPzGRuC58YBF9HxL3QB4lMLh7A4jG6wI+8QXrQ
 gjh0O1YVUzAe+NnuAH1Gg6eqZm9c4bTF1628mmbskbrfPuLDHRdneDK7sG/Mp9jMOYX2
 yzBC+NN+5Psqg8VWNU7KdXDY+vy1gkqGW8wpnqMUCRC68Nu3ESsmbT6YJ2c2nfyZq4yV
 JDxA==
X-Gm-Message-State: ALQs6tCgYouW+SHwFQHYve507U8G/iiZ97lrQ07OdKUu5UXQ88aBP+uo
 BYr0iWtuKFGjQ7mgiKhSiS0=
X-Google-Smtp-Source: AB8JxZrpW1OdYmMnN08Qovd4yUQB5rPzBIlbTHQL4QtDnZRS4+dWCHU2L+X01RojVegKU24mH426Xw==
X-Received: by 2002:adf:90cd:: with SMTP id
 i71-v6mr4260895wri.136.1525097273090; 
 Mon, 30 Apr 2018 07:07:53 -0700 (PDT)
Received: from localhost ([2a00:23c5:be9a:5200:ce4c:82c0:d567:ecbb])
 by smtp.gmail.com with ESMTPSA id h124sm17504375wma.35.2018.04.30.07.07.52
 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);
 Mon, 30 Apr 2018 07:07:52 -0700 (PDT)
From: luca.boccassi@gmail.com
To: Fan Zhang <roy.fan.zhang@intel.com>
Cc: Andrey Chilikin <andrey.chilikin@intel.com>,
 Eelco Chaudron <echaudro@redhat.com>, Wenzhuo Lu <wenzhuo.lu@intel.com>,
 dpdk stable <stable@dpdk.org>
Date: Mon, 30 Apr 2018 15:03:34 +0100
Message-Id: <20180430140606.4615-56-luca.boccassi@gmail.com>
X-Mailer: git-send-email 2.14.2
In-Reply-To: <20180430140606.4615-1-luca.boccassi@gmail.com>
References: <20180430140606.4615-1-luca.boccassi@gmail.com>
Subject: [dpdk-stable] patch 'net/i40e: fix link update no wait' has been
	queued to stable release 18.02.2
X-BeenThere: stable@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: patches for DPDK stable branches <stable.dpdk.org>
List-Unsubscribe: <https://dpdk.org/ml/options/stable>,
 <mailto:stable-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://dpdk.org/ml/archives/stable/>
List-Post: <mailto:stable@dpdk.org>
List-Help: <mailto:stable-request@dpdk.org?subject=help>
List-Subscribe: <https://dpdk.org/ml/listinfo/stable>,
 <mailto:stable-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Mon, 30 Apr 2018 14:07:53 -0000

Hi,

FYI, your patch has been queued to stable release 18.02.2

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 05/02/18. So please
shout if anyone has objections.

Thanks.

Luca Boccassi

---
>>From b4e1a9b51c5dc2b209ec634dd56b43e7f123dac7 Mon Sep 17 00:00:00 2001
From: Fan Zhang <roy.fan.zhang@intel.com>
Date: Thu, 8 Mar 2018 12:17:52 +0000
Subject: [PATCH] net/i40e: fix link update no wait

[ upstream commit eef2daf2e199d2a22eba0bdf9ee990c2a9efc101 ]

In i40e_dev_link_update() the driver obtains the link status
info via admin queue command despite of "no_wait" flag. This
requires relatively long time and may be a problem to some
application such as ovs-dpdk.
(https://bugzilla.redhat.com/show_bug.cgi?id=1551761).

This patch aims to fix the problem by using a different
approach of obtaining link status for i40e NIC without waiting.
Instead of getting the link status via admin queue command,
this patch reads the link status registers to accelerate the
procedure.

Fixes: 263333bbb7a9 ("i40e: fix link status timeout")

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com>
Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
Tested-by: Eelco Chaudron <echaudro@redhat.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 128 ++++++++++++++++++++++++++++++-----------
 1 file changed, 95 insertions(+), 33 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 508b4171c..968249ed1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -2437,77 +2437,139 @@ i40e_dev_set_link_down(struct rte_eth_dev *dev)
 	return i40e_phy_conf_link(hw, abilities, speed, false);
 }
 
-int
-i40e_dev_link_update(struct rte_eth_dev *dev,
-		     int wait_to_complete)
+static __rte_always_inline void
+update_link_no_wait(struct i40e_hw *hw, struct rte_eth_link *link)
 {
-#define CHECK_INTERVAL 100  /* 100ms */
-#define MAX_REPEAT_TIME 10  /* 1s (10 * 100ms) in total */
-	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+/* Link status registers and values*/
+#define I40E_PRTMAC_LINKSTA		0x001E2420
+#define I40E_REG_LINK_UP		0x40000080
+#define I40E_PRTMAC_MACC		0x001E24E0
+#define I40E_REG_MACC_25GB		0x00020000
+#define I40E_REG_SPEED_MASK		0x38000000
+#define I40E_REG_SPEED_100MB		0x00000000
+#define I40E_REG_SPEED_1GB		0x08000000
+#define I40E_REG_SPEED_10GB		0x10000000
+#define I40E_REG_SPEED_20GB		0x20000000
+#define I40E_REG_SPEED_25_40GB		0x18000000
+	uint32_t link_speed;
+	uint32_t reg_val;
+
+	reg_val = I40E_READ_REG(hw, I40E_PRTMAC_LINKSTA);
+	link_speed = reg_val & I40E_REG_SPEED_MASK;
+	reg_val &= I40E_REG_LINK_UP;
+	link->link_status = (reg_val == I40E_REG_LINK_UP) ? 1 : 0;
+
+	if (unlikely(link->link_status != 0))
+		return;
+
+	/* Parse the link status */
+	switch (link_speed) {
+	case I40E_REG_SPEED_100MB:
+		link->link_speed = ETH_SPEED_NUM_100M;
+		break;
+	case I40E_REG_SPEED_1GB:
+		link->link_speed = ETH_SPEED_NUM_1G;
+		break;
+	case I40E_REG_SPEED_10GB:
+		link->link_speed = ETH_SPEED_NUM_10G;
+		break;
+	case I40E_REG_SPEED_20GB:
+		link->link_speed = ETH_SPEED_NUM_20G;
+		break;
+	case I40E_REG_SPEED_25_40GB:
+		reg_val = I40E_READ_REG(hw, I40E_PRTMAC_MACC);
+
+		if (reg_val & I40E_REG_MACC_25GB)
+			link->link_speed = ETH_SPEED_NUM_25G;
+		else
+			link->link_speed = ETH_SPEED_NUM_40G;
+
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Unknown link speed info %u", link_speed);
+		break;
+	}
+}
+
+static __rte_always_inline void
+update_link_wait(struct i40e_hw *hw, struct rte_eth_link *link,
+	bool enable_lse)
+{
+#define CHECK_INTERVAL             100  /* 100ms */
+#define MAX_REPEAT_TIME            10  /* 1s (10 * 100ms) in total */
+	uint32_t rep_cnt = MAX_REPEAT_TIME;
 	struct i40e_link_status link_status;
-	struct rte_eth_link link, old;
 	int status;
-	unsigned rep_cnt = MAX_REPEAT_TIME;
-	bool enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false;
 
-	memset(&link, 0, sizeof(link));
-	memset(&old, 0, sizeof(old));
 	memset(&link_status, 0, sizeof(link_status));
-	rte_i40e_dev_atomic_read_link_status(dev, &old);
 
 	do {
 		/* Get link status information from hardware */
 		status = i40e_aq_get_link_info(hw, enable_lse,
 						&link_status, NULL);
-		if (status != I40E_SUCCESS) {
-			link.link_speed = ETH_SPEED_NUM_100M;
-			link.link_duplex = ETH_LINK_FULL_DUPLEX;
+		if (unlikely(status != I40E_SUCCESS)) {
+			link->link_speed = ETH_SPEED_NUM_100M;
+			link->link_duplex = ETH_LINK_FULL_DUPLEX;
 			PMD_DRV_LOG(ERR, "Failed to get link info");
-			goto out;
+			return;
 		}
 
-		link.link_status = link_status.link_info & I40E_AQ_LINK_UP;
-		if (!wait_to_complete || link.link_status)
-			break;
+		link->link_status = link_status.link_info & I40E_AQ_LINK_UP;
+		if (unlikely(link->link_status != 0))
+			return;
 
 		rte_delay_ms(CHECK_INTERVAL);
 	} while (--rep_cnt);
 
-	if (!link.link_status)
-		goto out;
-
-	/* i40e uses full duplex only */
-	link.link_duplex = ETH_LINK_FULL_DUPLEX;
-
 	/* Parse the link status */
 	switch (link_status.link_speed) {
 	case I40E_LINK_SPEED_100MB:
-		link.link_speed = ETH_SPEED_NUM_100M;
+		link->link_speed = ETH_SPEED_NUM_100M;
 		break;
 	case I40E_LINK_SPEED_1GB:
-		link.link_speed = ETH_SPEED_NUM_1G;
+		link->link_speed = ETH_SPEED_NUM_1G;
 		break;
 	case I40E_LINK_SPEED_10GB:
-		link.link_speed = ETH_SPEED_NUM_10G;
+		link->link_speed = ETH_SPEED_NUM_10G;
 		break;
 	case I40E_LINK_SPEED_20GB:
-		link.link_speed = ETH_SPEED_NUM_20G;
+		link->link_speed = ETH_SPEED_NUM_20G;
 		break;
 	case I40E_LINK_SPEED_25GB:
-		link.link_speed = ETH_SPEED_NUM_25G;
+		link->link_speed = ETH_SPEED_NUM_25G;
 		break;
 	case I40E_LINK_SPEED_40GB:
-		link.link_speed = ETH_SPEED_NUM_40G;
+		link->link_speed = ETH_SPEED_NUM_40G;
 		break;
 	default:
-		link.link_speed = ETH_SPEED_NUM_100M;
+		link->link_speed = ETH_SPEED_NUM_100M;
 		break;
 	}
+}
 
+int
+i40e_dev_link_update(struct rte_eth_dev *dev,
+		     int wait_to_complete)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_eth_link link, old;
+	bool enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false;
+
+	memset(&link, 0, sizeof(link));
+	memset(&old, 0, sizeof(old));
+
+	rte_i40e_dev_atomic_read_link_status(dev, &old);
+
+	/* i40e uses full duplex only */
+	link.link_duplex = ETH_LINK_FULL_DUPLEX;
 	link.link_autoneg = !(dev->data->dev_conf.link_speeds &
 			ETH_LINK_SPEED_FIXED);
 
-out:
+	if (!wait_to_complete)
+		update_link_no_wait(hw, &link);
+	else
+		update_link_wait(hw, &link, enable_lse);
+
 	rte_i40e_dev_atomic_write_link_status(dev, &link);
 	if (link.link_status == old.link_status)
 		return -1;
-- 
2.14.2