summaryrefslogtreecommitdiffstats
path: root/patches/dpdk_custom_patch/i40e-fix-link-management.patch
blob: af2c9a472317532cb453dc7b0531fb98beefd416 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
From ca7e599d4506f3d6b89dd846c901d09d46ea593c Mon Sep 17 00:00:00 2001
From: Jingjing Wu <jingjing.wu@intel.com>
Date: Thu, 12 May 2016 15:21:04 +0800
Subject: [PATCH] net/i40e: fix link management
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Previously, there was a known issue "On Intel® 40G Ethernet
Controller stopping the port does not really down the port link."

There were two reasons why the port was always kept up.
1. Old firmware versions had issues when "Set PHY config command"
   was used on 40G NICs.
2. The kernel i40e driver didn't call "Set PHY config command" when
   ifconfig up/down was used, it assumes the link is always up. But
   in DPDK, ports are forced down when an applications quits. So if
   the port is then switched to being controlled by kernel the driver,
   the port can not be brought up through "ifconfig <ethx> up".

This patch fixes this issue by adding in "Set PHY config command"
into our driver. This is now possible because with newer firmware
there is no longer a problem using this command.

With this fix, after DPDK quit, if the port is switched to being used
by the kernel driver, "ethtool -s <ethx> autoneg on" can be used to
turn on the auto negotiation, and then port can be brought up through
"ifconfig <ethx> up".
NOTE: requires kernel i40e driver version >= 1.4.X

Fixes: 2f1e22817420 ("i40e: skip link control as firmware workaround")
Fixes: 16c979f9adf2 ("i40e: disable setting of PHY configuration")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
---
 doc/guides/rel_notes/known_issues.rst | 19 ---------
 drivers/net/i40e/i40e_ethdev.c        | 72 +++++++++++++++++++++++++++++------
 2 files changed, 60 insertions(+), 31 deletions(-)

diff --git a/doc/guides/rel_notes/known_issues.rst b/doc/guides/rel_notes/known_issues.rst
index e464eca..5ec1987 100644
--- a/doc/guides/rel_notes/known_issues.rst
+++ b/doc/guides/rel_notes/known_issues.rst
@@ -532,25 +532,6 @@ Cannot set link speed on Intel® 40G Ethernet controller
    Poll Mode Driver (PMD).
 
 
-Stopping the port does not down the link on Intel® 40G Ethernet controller
---------------------------------------------------------------------------
-
-**Description**:
-   On Intel® 40G Ethernet Controller stopping the port does not really down the port link.
-
-**Implication**:
-   The port link will be still up after stopping the port.
-
-**Resolution/Workaround**:
-   None
-
-**Affected Environment/Platform**:
-   All.
-
-**Driver/Module**:
-   Poll Mode Driver (PMD).
-
-
 Devices bound to igb_uio with VT-d enabled do not work on Linux kernel 3.15-3.17
 --------------------------------------------------------------------------------
 
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index f94ad87..7a94663 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1407,15 +1407,58 @@ i40e_parse_link_speeds(uint16_t link_speeds)
 }
 
 static int
-i40e_phy_conf_link(__rte_unused struct i40e_hw *hw,
-		   __rte_unused uint8_t abilities,
-		   __rte_unused uint8_t force_speed)
-{
-	/* Skip any phy config on both 10G and 40G interfaces, as a workaround
-	 * for the link control limitation of that all link control should be
-	 * handled by firmware. It should follow up if link control will be
-	 * opened to software driver in future firmware versions.
-	 */
+i40e_phy_conf_link(struct i40e_hw *hw,
+		   uint8_t abilities,
+		   uint8_t force_speed)
+{
+	enum i40e_status_code status;
+	struct i40e_aq_get_phy_abilities_resp phy_ab;
+	struct i40e_aq_set_phy_config phy_conf;
+	const uint8_t mask = I40E_AQ_PHY_FLAG_PAUSE_TX |
+			I40E_AQ_PHY_FLAG_PAUSE_RX |
+			I40E_AQ_PHY_FLAG_PAUSE_RX |
+			I40E_AQ_PHY_FLAG_LOW_POWER;
+	const uint8_t advt = I40E_LINK_SPEED_40GB |
+			I40E_LINK_SPEED_10GB |
+			I40E_LINK_SPEED_1GB |
+			I40E_LINK_SPEED_100MB;
+	int ret = -ENOTSUP;
+
+
+	status = i40e_aq_get_phy_capabilities(hw, false, false, &phy_ab,
+					      NULL);
+	if (status)
+		return ret;
+
+	memset(&phy_conf, 0, sizeof(phy_conf));
+
+	/* bits 0-2 use the values from get_phy_abilities_resp */
+	abilities &= ~mask;
+	abilities |= phy_ab.abilities & mask;
+
+	/* update ablities and speed */
+	if (abilities & I40E_AQ_PHY_AN_ENABLED)
+		phy_conf.link_speed = advt;
+	else
+		phy_conf.link_speed = force_speed;
+
+	phy_conf.abilities = abilities;
+
+	/* use get_phy_abilities_resp value for the rest */
+	phy_conf.phy_type = phy_ab.phy_type;
+	phy_conf.eee_capability = phy_ab.eee_capability;
+	phy_conf.eeer = phy_ab.eeer_val;
+	phy_conf.low_power_ctrl = phy_ab.d3_lpan;
+
+	PMD_DRV_LOG(DEBUG, "\tCurrent: abilities %x, link_speed %x",
+		    phy_ab.abilities, phy_ab.link_speed);
+	PMD_DRV_LOG(DEBUG, "\tConfig:  abilities %x, link_speed %x",
+		    phy_conf.abilities, phy_conf.link_speed);
+
+	status = i40e_aq_set_phy_config(hw, &phy_conf, NULL);
+	if (status)
+		return ret;
+
 	return I40E_SUCCESS;
 }
 
@@ -1431,8 +1474,13 @@ i40e_apply_link_speed(struct rte_eth_dev *dev)
 	abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
 	if (!(conf->link_speeds & ETH_LINK_SPEED_FIXED))
 		abilities |= I40E_AQ_PHY_AN_ENABLED;
-	else
-		abilities |= I40E_AQ_PHY_LINK_ENABLED;
+	abilities |= I40E_AQ_PHY_LINK_ENABLED;
+
+	/* Skip changing speed on 40G interfaces, FW does not support */
+	if (i40e_is_40G_device(hw->device_id)) {
+		speed =  I40E_LINK_SPEED_UNKNOWN;
+		abilities |= I40E_AQ_PHY_AN_ENABLED;
+	}
 
 	return i40e_phy_conf_link(hw, abilities, speed);
 }
@@ -1742,7 +1790,7 @@ i40e_dev_set_link_up(struct rte_eth_dev *dev)
  * Set device link down.
  */
 static int
-i40e_dev_set_link_down(__rte_unused struct rte_eth_dev *dev)
+i40e_dev_set_link_down(struct rte_eth_dev *dev)
 {
 	uint8_t speed = I40E_LINK_SPEED_UNKNOWN;
 	uint8_t abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
-- 
2.7.4