[dpdk-dev,v2,2/3] net/mlx5: fix link status behavior

Message ID f0340cb5f3067ff5031794ad8fc7852dd10d9a76.1520862100.git.nelio.laranjeiro@6wind.com (mailing list archive)
State Accepted, archived
Delegated to: Shahaf Shuler
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail apply issues

Commit Message

Nélio Laranjeiro March 12, 2018, 1:43 p.m. UTC
  This behavior is mixed between what should be handled by the application
and what is under PMD responsibility.

According to DPDK API:
- link_update() should only query the link status [1]
- link_set_{up,down}() should only set the link to the according status [1]
- dev_{start,stop}() should enable/disable traffic reception/emission [2]

On this PMD, the link status is retrieved from the net device associated
owned by the Linux Kernel, it does not means that even when this interface
is down, the PMD cannot send/receive traffic from the NIC those two
information are unrelated, until the physical port is active and has a
link, the PMD can receive/send traffic on the wire.

According to DPDK API, calling the rte_eth_dev_start() even when the Linux
interface link is down is then possible and allowed, as the traffic will
flow between the DPDK application and the Physical port.

This also means that a synchronisation between the Linux interface and the
DPDK application remains under the DPDK application responsibility.

To handle such synchronisation the application should behave as the
following scheme, to start:

 rte_eth_get_link(port_id, &link);
 if (link.link_status == ETH_DOWN)
	rte_eth_dev_set_link_up(port_id);
 rte_eth_dev_start(port_id);

Taking in account the possible returned values fro each function.

and to stop:

 rte_eth_dev_stop(port_id);
 rte_eth_dev_set_link_down(port_id);

The application should also set the LSC interrupt callbacks to catch and
behave accordingly when the administrator set the Linux device down/up.
The same callbacks are called when the link on the medium falls/raise.

Fixes: c7bf62255edf ("net/mlx5: fix handling link status event")
Fixes: e313ef4c2fe8 ("net/mlx5: fix link state on device start")
Cc: yskoh@mellanox.com
Cc: shahafs@mellanox.com
Cc: stable@dpdk.org

[1] https://dpdk.org/browse/dpdk/tree/lib/librte_ether/rte_ethdev_core.h
[2] https://dpdk.org/browse/dpdk/tree/lib/librte_ether/rte_ethdev.h#n1677

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx5/mlx5.c         |  2 +-
 drivers/net/mlx5/mlx5_ethdev.c  | 92 +----------------------------------------
 drivers/net/mlx5/mlx5_trigger.c | 15 ++++---
 3 files changed, 12 insertions(+), 97 deletions(-)
  

Comments

Yongseok Koh March 13, 2018, 9:54 p.m. UTC | #1
On Mon, Mar 12, 2018 at 02:43:18PM +0100, Nelio Laranjeiro wrote:
> This behavior is mixed between what should be handled by the application
> and what is under PMD responsibility.
> 
> According to DPDK API:
> - link_update() should only query the link status [1]
> - link_set_{up,down}() should only set the link to the according status [1]
> - dev_{start,stop}() should enable/disable traffic reception/emission [2]

The description of rte_eth_dev_set_link_up() is [1] :
	The device rx/tx functionality will be disabled if success, and it can
	be re-enabled with a call to rte_eth_dev_set_link_up()

This means, if user runs "set link-down port 0" on testpmd, traffic should stop
by disabling Rx/Tx on device. But unfortunately, mlx5 doesn't have a way to stop
device but it rather relies on kernel implementation - e.g. SIOCSIFFLAGS. So,
even if the command is run, traffic goes on. I guess the original
implementation might be needed to workaround this situation.

Shall we talk to HW and driver people regarding how to access dev (or PHY) from
user-level?

[1] http://dpdk.org/doc/api/rte__ethdev_8h.html#a51d7a0d2bb4202f9ebf9f174ba1f6e5c

Thanks,
Yongseok
  
Adrien Mazarguil March 14, 2018, 12:18 p.m. UTC | #2
On Tue, Mar 13, 2018 at 02:54:44PM -0700, Yongseok Koh wrote:
> On Mon, Mar 12, 2018 at 02:43:18PM +0100, Nelio Laranjeiro wrote:
> > This behavior is mixed between what should be handled by the application
> > and what is under PMD responsibility.
> > 
> > According to DPDK API:
> > - link_update() should only query the link status [1]
> > - link_set_{up,down}() should only set the link to the according status [1]
> > - dev_{start,stop}() should enable/disable traffic reception/emission [2]
> 
> The description of rte_eth_dev_set_link_up() is [1] :
> 	The device rx/tx functionality will be disabled if success, and it can
> 	be re-enabled with a call to rte_eth_dev_set_link_up()
> 
> This means, if user runs "set link-down port 0" on testpmd, traffic should stop
> by disabling Rx/Tx on device. But unfortunately, mlx5 doesn't have a way to stop
> device but it rather relies on kernel implementation - e.g. SIOCSIFFLAGS. So,
> even if the command is run, traffic goes on. I guess the original
> implementation might be needed to workaround this situation.
> 
> Shall we talk to HW and driver people regarding how to access dev (or PHY) from
> user-level?
> 
> [1] http://dpdk.org/doc/api/rte__ethdev_8h.html#a51d7a0d2bb4202f9ebf9f174ba1f6e5c

As you mentioned, since the mlx5 PMD doesn't really own the device, it
doesn't have the final say on whether traffic still flows after putting the
link down at the DPDK level. It has been worked around by replacing burst
callbacks with no-ops since up/down ethops were added [3].

Problem is that updating burst callback pointers while traffic is flowing
has always been more or less unsafe. It's not necessarily atomic and only
really safe to do when traffic is guaranteed to be stopped (i.e. after
dev_stop() was called by the application). Moreover these no-ops don't
prevent device RX queues from still getting filled up.

Looking at the original implementation [4][5], other PMDs simply have to
turn off the laser or some such which doesn't prevent RX/TX functions from
working as before except traffic happens to be lost instead of ending up
rejected by dedicated burst callbacks.

The main purpose of up/down callbacks and the reason they were implemented
in mlx5 is that customers want to see something happen at the carrier level
on the remote end (as with other PMDs) when a DPDK port is brought up or
down. This is why they are seldom implemented in other PMDs for VF
eth_dev_ops given those can't control PHY.

Actively preventing traffic is secondary and either has a performance impact
(permanent status check in the data plane) or is somewhat unsafe (live
replacement of burst callbacks).

Given the above, I'm in favor of removing the no-ops. Applications are the
ones performing up/down calls, they manage the administrative status of
interfaces and should refrain from calling TX/RX burst functions
afterward. Carrier status is left to PMDs and can't necessarily be modified.

[3] 62072098b54e ("mlx5: support setting link up or down")
[4] 915e67837586 ("ethdev: API for link up and down")
[5] c38f4f83edc0 ("ixgbe: link up and down")
  
Nélio Laranjeiro March 14, 2018, 12:22 p.m. UTC | #3
On Tue, Mar 13, 2018 at 02:54:44PM -0700, Yongseok Koh wrote:
> On Mon, Mar 12, 2018 at 02:43:18PM +0100, Nelio Laranjeiro wrote:
> > This behavior is mixed between what should be handled by the application
> > and what is under PMD responsibility.
> > 
> > According to DPDK API:
> > - link_update() should only query the link status [1]
> > - link_set_{up,down}() should only set the link to the according status [1]
> > - dev_{start,stop}() should enable/disable traffic reception/emission [2]
> 
> The description of rte_eth_dev_set_link_up() is [1] :
> 	The device rx/tx functionality will be disabled if success, and it can
> 	be re-enabled with a call to rte_eth_dev_set_link_up()
> 
> This means, if user runs "set link-down port 0" on testpmd, traffic should stop
> by disabling Rx/Tx on device. But unfortunately, mlx5 doesn't have a way to stop
> device but it rather relies on kernel implementation - e.g. SIOCSIFFLAGS. So,
> even if the command is run, traffic goes on. I guess the original
> implementation might be needed to workaround this situation.

As you mention the traffic is not disabled on the hardware, which also
means that replacing the burst functions does not solve anything, it
just moves the issue.
The fact is, the queues can still send/receive traffic even if the link
is down.  Not polling them won't solve the fact that Rx queues will
still receive traffic addressed to the application.

Considering an application should not try to send nor poll traffic once
it has set the link down and this, until it sets the link up, the
behavior is identical to the "original" code i.e. at the first poll, the
application will receive enqueued packets in the Rx queues while the
link was down.

> Shall we talk to HW and driver people regarding how to access dev (or PHY) from
> user-level?

We can.

> [1] http://dpdk.org/doc/api/rte__ethdev_8h.html#a51d7a0d2bb4202f9ebf9f174ba1f6e5c

Regards,
  
Yongseok Koh March 14, 2018, 5:40 p.m. UTC | #4
On Wed, Mar 14, 2018 at 01:18:56PM +0100, Adrien Mazarguil wrote:
> On Tue, Mar 13, 2018 at 02:54:44PM -0700, Yongseok Koh wrote:
> > On Mon, Mar 12, 2018 at 02:43:18PM +0100, Nelio Laranjeiro wrote:
> > > This behavior is mixed between what should be handled by the application
> > > and what is under PMD responsibility.
> > > 
> > > According to DPDK API:
> > > - link_update() should only query the link status [1]
> > > - link_set_{up,down}() should only set the link to the according status [1]
> > > - dev_{start,stop}() should enable/disable traffic reception/emission [2]
> > 
> > The description of rte_eth_dev_set_link_up() is [1] :
> > 	The device rx/tx functionality will be disabled if success, and it can
> > 	be re-enabled with a call to rte_eth_dev_set_link_up()
> > 
> > This means, if user runs "set link-down port 0" on testpmd, traffic should stop
> > by disabling Rx/Tx on device. But unfortunately, mlx5 doesn't have a way to stop
> > device but it rather relies on kernel implementation - e.g. SIOCSIFFLAGS. So,
> > even if the command is run, traffic goes on. I guess the original
> > implementation might be needed to workaround this situation.
> > 
> > Shall we talk to HW and driver people regarding how to access dev (or PHY) from
> > user-level?
> > 
> > [1] https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdpdk.org%2Fdoc%2Fapi%2Frte__ethdev_8h.html%23a51d7a0d2bb4202f9ebf9f174ba1f6e5c&data=02%7C01%7Cyskoh%40mellanox.com%7C346b9914b7664dcf0e7008d589a5cb53%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636566267555398866&sdata=Ad1%2FyQqyXeifXFJjxMMRxq81YGpF7nEFHvaX28nncl8%3D&reserved=0
> 
> As you mentioned, since the mlx5 PMD doesn't really own the device, it
> doesn't have the final say on whether traffic still flows after putting the
> link down at the DPDK level. It has been worked around by replacing burst
> callbacks with no-ops since up/down ethops were added [3].
> 
> Problem is that updating burst callback pointers while traffic is flowing
> has always been more or less unsafe. It's not necessarily atomic and only
> really safe to do when traffic is guaranteed to be stopped (i.e. after
> dev_stop() was called by the application). Moreover these no-ops don't
> prevent device RX queues from still getting filled up.
> 
> Looking at the original implementation [4][5], other PMDs simply have to
> turn off the laser or some such which doesn't prevent RX/TX functions from
> working as before except traffic happens to be lost instead of ending up
> rejected by dedicated burst callbacks.
> 
> The main purpose of up/down callbacks and the reason they were implemented
> in mlx5 is that customers want to see something happen at the carrier level
> on the remote end (as with other PMDs) when a DPDK port is brought up or
> down. This is why they are seldom implemented in other PMDs for VF
> eth_dev_ops given those can't control PHY.
> 
> Actively preventing traffic is secondary and either has a performance impact
> (permanent status check in the data plane) or is somewhat unsafe (live
> replacement of burst callbacks).
> 
> Given the above, I'm in favor of removing the no-ops. Applications are the
> ones performing up/down calls, they manage the administrative status of
> interfaces and should refrain from calling TX/RX burst functions
> afterward. Carrier status is left to PMDs and can't necessarily be modified.
> 
> [3] 62072098b54e ("mlx5: support setting link up or down")
> [4] 915e67837586 ("ethdev: API for link up and down")
> [5] c38f4f83edc0 ("ixgbe: link up and down")

Adrien, Nelio

Please don't get me wrong. I didn't mean to defend the status quo. I didn't like
the null burst function either since I firstly joined this project. I was just
mentioning it was anyway non-compliant to the document and suggesting to find
out a better way if any, e.g. accessing PHY. Even if you don't think it is a
critical matter, there's no need to change the kernel flag and we just can make
dev_set_link_down/up() return without doing anything. If we can't/don't change
carrier status in the functions and those funcs have no effect, how about not
changing the kernel interface flag? Or, if you still insist no change is needed
in this patch, that is also fine to me as this isn't a critical path and doesn't
have any erroneous behavior.

Thanks,
Yongseok
  
Adrien Mazarguil March 14, 2018, 7 p.m. UTC | #5
On Wed, Mar 14, 2018 at 10:40:59AM -0700, Yongseok Koh wrote:
> On Wed, Mar 14, 2018 at 01:18:56PM +0100, Adrien Mazarguil wrote:
> > On Tue, Mar 13, 2018 at 02:54:44PM -0700, Yongseok Koh wrote:
> > > On Mon, Mar 12, 2018 at 02:43:18PM +0100, Nelio Laranjeiro wrote:
> > > > This behavior is mixed between what should be handled by the application
> > > > and what is under PMD responsibility.
> > > > 
> > > > According to DPDK API:
> > > > - link_update() should only query the link status [1]
> > > > - link_set_{up,down}() should only set the link to the according status [1]
> > > > - dev_{start,stop}() should enable/disable traffic reception/emission [2]
> > > 
> > > The description of rte_eth_dev_set_link_up() is [1] :
> > > 	The device rx/tx functionality will be disabled if success, and it can
> > > 	be re-enabled with a call to rte_eth_dev_set_link_up()
> > > 
> > > This means, if user runs "set link-down port 0" on testpmd, traffic should stop
> > > by disabling Rx/Tx on device. But unfortunately, mlx5 doesn't have a way to stop
> > > device but it rather relies on kernel implementation - e.g. SIOCSIFFLAGS. So,
> > > even if the command is run, traffic goes on. I guess the original
> > > implementation might be needed to workaround this situation.
> > > 
> > > Shall we talk to HW and driver people regarding how to access dev (or PHY) from
> > > user-level?
> > > 
> > > [1] https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdpdk.org%2Fdoc%2Fapi%2Frte__ethdev_8h.html%23a51d7a0d2bb4202f9ebf9f174ba1f6e5c&data=02%7C01%7Cyskoh%40mellanox.com%7C346b9914b7664dcf0e7008d589a5cb53%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636566267555398866&sdata=Ad1%2FyQqyXeifXFJjxMMRxq81YGpF7nEFHvaX28nncl8%3D&reserved=0
> > 
> > As you mentioned, since the mlx5 PMD doesn't really own the device, it
> > doesn't have the final say on whether traffic still flows after putting the
> > link down at the DPDK level. It has been worked around by replacing burst
> > callbacks with no-ops since up/down ethops were added [3].
> > 
> > Problem is that updating burst callback pointers while traffic is flowing
> > has always been more or less unsafe. It's not necessarily atomic and only
> > really safe to do when traffic is guaranteed to be stopped (i.e. after
> > dev_stop() was called by the application). Moreover these no-ops don't
> > prevent device RX queues from still getting filled up.
> > 
> > Looking at the original implementation [4][5], other PMDs simply have to
> > turn off the laser or some such which doesn't prevent RX/TX functions from
> > working as before except traffic happens to be lost instead of ending up
> > rejected by dedicated burst callbacks.
> > 
> > The main purpose of up/down callbacks and the reason they were implemented
> > in mlx5 is that customers want to see something happen at the carrier level
> > on the remote end (as with other PMDs) when a DPDK port is brought up or
> > down. This is why they are seldom implemented in other PMDs for VF
> > eth_dev_ops given those can't control PHY.
> > 
> > Actively preventing traffic is secondary and either has a performance impact
> > (permanent status check in the data plane) or is somewhat unsafe (live
> > replacement of burst callbacks).
> > 
> > Given the above, I'm in favor of removing the no-ops. Applications are the
> > ones performing up/down calls, they manage the administrative status of
> > interfaces and should refrain from calling TX/RX burst functions
> > afterward. Carrier status is left to PMDs and can't necessarily be modified.
> > 
> > [3] 62072098b54e ("mlx5: support setting link up or down")
> > [4] 915e67837586 ("ethdev: API for link up and down")
> > [5] c38f4f83edc0 ("ixgbe: link up and down")
> 
> Adrien, Nelio
> 
> Please don't get me wrong. I didn't mean to defend the status quo. I didn't like
> the null burst function either since I firstly joined this project. I was just
> mentioning it was anyway non-compliant to the document and suggesting to find
> out a better way if any, e.g. accessing PHY. Even if you don't think it is a
> critical matter, there's no need to change the kernel flag and we just can make
> dev_set_link_down/up() return without doing anything. If we can't/don't change
> carrier status in the functions and those funcs have no effect, how about not
> changing the kernel interface flag? Or, if you still insist no change is needed
> in this patch, that is also fine to me as this isn't a critical path and doesn't
> have any erroneous behavior.

Heh, all right, I felt obligated to describe how it ended up like that.

I agree that somehow controlling PHY should be OK assuming there was a way
to do it. Currently bringing the netdevice down achieves the desired effect
with PF devices (well, at least it should, according to memory).

The code is the same for VF devices though it has no effect on them, perhaps
we could do like other PMDs by providing a separate set of eth_dev_ops
without up/down capabilities.

One problem will always remain though: an external application can always
re-enable PHY through other interfaces, resuming traffic by doing so.
  
Yongseok Koh March 15, 2018, 6:08 p.m. UTC | #6
> On Mar 12, 2018, at 6:43 AM, Nelio Laranjeiro <nelio.laranjeiro@6wind.com> wrote:
> 
> This behavior is mixed between what should be handled by the application
> and what is under PMD responsibility.
> 
> According to DPDK API:
> - link_update() should only query the link status [1]
> - link_set_{up,down}() should only set the link to the according status [1]
> - dev_{start,stop}() should enable/disable traffic reception/emission [2]
> 
> On this PMD, the link status is retrieved from the net device associated
> owned by the Linux Kernel, it does not means that even when this interface
> is down, the PMD cannot send/receive traffic from the NIC those two
> information are unrelated, until the physical port is active and has a
> link, the PMD can receive/send traffic on the wire.
> 
> According to DPDK API, calling the rte_eth_dev_start() even when the Linux
> interface link is down is then possible and allowed, as the traffic will
> flow between the DPDK application and the Physical port.
> 
> This also means that a synchronisation between the Linux interface and the
> DPDK application remains under the DPDK application responsibility.
> 
> To handle such synchronisation the application should behave as the
> following scheme, to start:
> 
> rte_eth_get_link(port_id, &link);
> if (link.link_status == ETH_DOWN)
> 	rte_eth_dev_set_link_up(port_id);
> rte_eth_dev_start(port_id);
> 
> Taking in account the possible returned values fro each function.
> 
> and to stop:
> 
> rte_eth_dev_stop(port_id);
> rte_eth_dev_set_link_down(port_id);
> 
> The application should also set the LSC interrupt callbacks to catch and
> behave accordingly when the administrator set the Linux device down/up.
> The same callbacks are called when the link on the medium falls/raise.
> 
> Fixes: c7bf62255edf ("net/mlx5: fix handling link status event")
> Fixes: e313ef4c2fe8 ("net/mlx5: fix link state on device start")
> Cc: yskoh@mellanox.com
> Cc: shahafs@mellanox.com
> Cc: stable@dpdk.org
> 
> [1] https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdpdk.org%2Fbrowse%2Fdpdk%2Ftree%2Flib%2Flibrte_ether%2Frte_ethdev_core.h&data=02%7C01%7Cyskoh%40mellanox.com%7Cf3d27421af9541c0d74608d5881f67af%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636564590830553144&sdata=dn%2BQOq9IG2O4eYC7aSAMjvQ%2BT9rkVW%2BRo7t9RxLODTk%3D&reserved=0
> [2] https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdpdk.org%2Fbrowse%2Fdpdk%2Ftree%2Flib%2Flibrte_ether%2Frte_ethdev.h%23n1677&data=02%7C01%7Cyskoh%40mellanox.com%7Cf3d27421af9541c0d74608d5881f67af%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636564590830553144&sdata=2zY%2F9gpIRcjz1mo4442u9uHTJPj5GVRftxHW8oVi6Ug%3D&reserved=0
> 
> Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
> Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
> ---
Acked-by: Yongseok Koh <yskoh@mellanox.com>
 
Thanks
  

Patch

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 4300bafb7..35a018758 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -962,7 +962,7 @@  mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		/* Bring Ethernet device up. */
 		DRV_LOG(DEBUG, "port %u forcing Ethernet interface up",
 			eth_dev->data->port_id);
-		mlx5_set_flags(eth_dev, ~IFF_UP, IFF_UP);
+		mlx5_set_link_up(eth_dev);
 		/* Store device configuration on private structure. */
 		priv->config = config;
 		continue;
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index 26f13fb1b..10ba27c79 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -645,80 +645,6 @@  mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev)
 }
 
 /**
- * Enable receiving and transmitting traffic.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-static void
-mlx5_link_start(struct rte_eth_dev *dev)
-{
-	struct priv *priv = dev->data->dev_private;
-	int ret;
-
-	dev->tx_pkt_burst = mlx5_select_tx_function(dev);
-	dev->rx_pkt_burst = mlx5_select_rx_function(dev);
-	ret = mlx5_traffic_enable(dev);
-	if (ret) {
-		DRV_LOG(ERR,
-			"port %u error occurred while configuring control"
-			" flows: %s",
-			dev->data->port_id, strerror(rte_errno));
-		return;
-	}
-	ret = mlx5_flow_start(dev, &priv->flows);
-	if (ret)
-		DRV_LOG(ERR,
-			"port %u error occurred while configuring flows: %s",
-			dev->data->port_id, strerror(rte_errno));
-}
-
-/**
- * Disable receiving and transmitting traffic.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-static void
-mlx5_link_stop(struct rte_eth_dev *dev)
-{
-	struct priv *priv = dev->data->dev_private;
-
-	mlx5_flow_stop(dev, &priv->flows);
-	mlx5_traffic_disable(dev);
-	dev->rx_pkt_burst = removed_rx_burst;
-	dev->tx_pkt_burst = removed_tx_burst;
-}
-
-/**
- * Querying the link status till it changes to the desired state.
- * Number of query attempts is bounded by MLX5_MAX_LINK_QUERY_ATTEMPTS.
- *
- * @param dev
- *   Pointer to Ethernet device.
- * @param status
- *   Link desired status.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-int
-mlx5_force_link_status_change(struct rte_eth_dev *dev, int status)
-{
-	int try = 0;
-
-	while (try < MLX5_MAX_LINK_QUERY_ATTEMPTS) {
-		mlx5_link_update(dev, 0);
-		if (dev->data->dev_link.link_status == status)
-			return 0;
-		try++;
-		sleep(1);
-	}
-	rte_errno = EAGAIN;
-	return -rte_errno;
-}
-
-/**
  * DPDK callback to retrieve physical link information.
  *
  * @param dev
@@ -733,26 +659,10 @@  int
 mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
 {
 	int ret;
-	struct rte_eth_link dev_link = dev->data->dev_link;
 
 	ret = mlx5_link_update_unlocked_gset(dev);
-	if (ret) {
+	if (ret)
 		ret = mlx5_link_update_unlocked_gs(dev);
-		if (ret)
-			return ret;
-	}
-	/* If lsc interrupt is disabled, should always be ready for traffic. */
-	if (!dev->data->dev_conf.intr_conf.lsc) {
-		mlx5_link_start(dev);
-		return 0;
-	}
-	/* Re-select burst callbacks only if link status has been changed. */
-	if (!ret && dev_link.link_status != dev->data->dev_link.link_status) {
-		if (dev->data->dev_link.link_status == ETH_LINK_UP)
-			mlx5_link_start(dev);
-		else
-			mlx5_link_stop(dev);
-	}
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c
index 28770b8eb..6bb4ffb14 100644
--- a/drivers/net/mlx5/mlx5_trigger.c
+++ b/drivers/net/mlx5/mlx5_trigger.c
@@ -176,15 +176,20 @@  mlx5_dev_start(struct rte_eth_dev *dev)
 		goto error;
 	}
 	mlx5_xstats_init(dev);
-	/* Update link status and Tx/Rx callbacks for the first time. */
-	memset(&dev->data->dev_link, 0, sizeof(struct rte_eth_link));
-	DRV_LOG(INFO, "forcing port %u link to be up", dev->data->port_id);
-	ret = mlx5_force_link_status_change(dev, ETH_LINK_UP);
+	ret = mlx5_traffic_enable(dev);
 	if (ret) {
-		DRV_LOG(DEBUG, "failed to set port %u link to be up",
+		DRV_LOG(DEBUG, "port %u failed to set defaults flows",
 			dev->data->port_id);
 		goto error;
 	}
+	ret = mlx5_flow_start(dev, &priv->flows);
+	if (ret) {
+		DRV_LOG(DEBUG, "port %u failed to set flows",
+			dev->data->port_id);
+		goto error;
+	}
+	dev->tx_pkt_burst = mlx5_select_tx_function(dev);
+	dev->rx_pkt_burst = mlx5_select_rx_function(dev);
 	mlx5_dev_interrupt_handler_install(dev);
 	return 0;
 error: