[v2,14/62] net/cnxk: add link status update support

Message ID 20210607175943.31690-15-ndabilpuram@marvell.com (mailing list archive)
State Changes Requested, archived
Delegated to: Jerin Jacob
Headers
Series Marvell CNXK Ethdev Driver |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Nithin Dabilpuram June 7, 2021, 5:58 p.m. UTC
  Add link status update callback to get current
link status.

Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
---
 doc/guides/nics/cnxk.rst              |   1 +
 doc/guides/nics/features/cnxk.ini     |   2 +
 doc/guides/nics/features/cnxk_vec.ini |   2 +
 doc/guides/nics/features/cnxk_vf.ini  |   2 +
 drivers/net/cnxk/cnxk_ethdev.c        |   7 +++
 drivers/net/cnxk/cnxk_ethdev.h        |   8 +++
 drivers/net/cnxk/cnxk_link.c          | 102 ++++++++++++++++++++++++++++++++++
 drivers/net/cnxk/meson.build          |   3 +-
 8 files changed, 126 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/cnxk/cnxk_link.c
  

Comments

Jerin Jacob June 15, 2021, 12:31 p.m. UTC | #1
On Mon, Jun 7, 2021 at 11:35 PM Nithin Dabilpuram
<ndabilpuram@marvell.com> wrote:
>
> Add link status update callback to get current
> link status.
>
> Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
> ---
>  doc/guides/nics/cnxk.rst              |   1 +
>  doc/guides/nics/features/cnxk.ini     |   2 +
>  doc/guides/nics/features/cnxk_vec.ini |   2 +
>  doc/guides/nics/features/cnxk_vf.ini  |   2 +
>  drivers/net/cnxk/cnxk_ethdev.c        |   7 +++
>  drivers/net/cnxk/cnxk_ethdev.h        |   8 +++
>  drivers/net/cnxk/cnxk_link.c          | 102 ++++++++++++++++++++++++++++++++++
>  drivers/net/cnxk/meson.build          |   3 +-
>  8 files changed, 126 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/net/cnxk/cnxk_link.c
>
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2021 Marvell.
> + */
> +
> +#include "cnxk_ethdev.h"
> +
> +static inline int
> +nix_wait_for_link_cfg(struct cnxk_eth_dev *dev)
> +{
> +       uint16_t wait = 1000;
> +
> +       do {
> +               rte_rmb();

Please use gcc atomics instead.

With above change:

Reviewed-by: Jerin Jacob <jerinj@marvell.com>

> +               if (!(dev->flags & CNXK_LINK_CFG_IN_PROGRESS_F))
> +                       break;
> +               wait--;
> +               rte_delay_ms(1);
> +       } while (wait);
> +
> +       return wait ? 0 : -1;
> +}
>
  

Patch

diff --git a/doc/guides/nics/cnxk.rst b/doc/guides/nics/cnxk.rst
index 73eb62a..a982450 100644
--- a/doc/guides/nics/cnxk.rst
+++ b/doc/guides/nics/cnxk.rst
@@ -20,6 +20,7 @@  Features of the CNXK Ethdev PMD are:
 - Lock-free Tx queue
 - Multiple queues for TX and RX
 - Receiver Side Scaling (RSS)
+- Link state information
 
 Prerequisites
 -------------
diff --git a/doc/guides/nics/features/cnxk.ini b/doc/guides/nics/features/cnxk.ini
index 96dba2a..affbbd9 100644
--- a/doc/guides/nics/features/cnxk.ini
+++ b/doc/guides/nics/features/cnxk.ini
@@ -8,6 +8,8 @@  Speed capabilities   = Y
 Lock-free Tx queue   = Y
 SR-IOV               = Y
 Multiprocess aware   = Y
+Link status          = Y
+Link status event    = Y
 RSS hash             = Y
 Inner RSS            = Y
 Linux                = Y
diff --git a/doc/guides/nics/features/cnxk_vec.ini b/doc/guides/nics/features/cnxk_vec.ini
index 616991c..836cc9f 100644
--- a/doc/guides/nics/features/cnxk_vec.ini
+++ b/doc/guides/nics/features/cnxk_vec.ini
@@ -8,6 +8,8 @@  Speed capabilities   = Y
 Lock-free Tx queue   = Y
 SR-IOV               = Y
 Multiprocess aware   = Y
+Link status          = Y
+Link status event    = Y
 RSS hash             = Y
 Inner RSS            = Y
 Linux                = Y
diff --git a/doc/guides/nics/features/cnxk_vf.ini b/doc/guides/nics/features/cnxk_vf.ini
index a0bd2f1..29bb24f 100644
--- a/doc/guides/nics/features/cnxk_vf.ini
+++ b/doc/guides/nics/features/cnxk_vf.ini
@@ -7,6 +7,8 @@ 
 Speed capabilities   = Y
 Lock-free Tx queue   = Y
 Multiprocess aware   = Y
+Link status          = Y
+Link status event    = Y
 RSS hash             = Y
 Inner RSS            = Y
 Linux                = Y
diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c
index 7824f3b..1d7e0a7 100644
--- a/drivers/net/cnxk/cnxk_ethdev.c
+++ b/drivers/net/cnxk/cnxk_ethdev.c
@@ -572,6 +572,7 @@  cnxk_nix_configure(struct rte_eth_dev *eth_dev)
 /* CNXK platform independent eth dev ops */
 struct eth_dev_ops cnxk_eth_dev_ops = {
 	.dev_infos_get = cnxk_nix_info_get,
+	.link_update = cnxk_nix_link_update,
 };
 
 static int
@@ -607,6 +608,9 @@  cnxk_eth_dev_init(struct rte_eth_dev *eth_dev)
 		goto error;
 	}
 
+	/* Register up msg callbacks */
+	roc_nix_mac_link_cb_register(nix, cnxk_eth_dev_link_status_cb);
+
 	dev->eth_dev = eth_dev;
 	dev->configured = 0;
 
@@ -695,6 +699,9 @@  cnxk_eth_dev_uninit(struct rte_eth_dev *eth_dev, bool mbox_close)
 
 	roc_nix_npc_rx_ena_dis(nix, false);
 
+	/* Disable link status events */
+	roc_nix_mac_link_event_start_stop(nix, false);
+
 	/* Free up SQs */
 	for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
 		dev_ops->tx_queue_release(eth_dev->data->tx_queues[i]);
diff --git a/drivers/net/cnxk/cnxk_ethdev.h b/drivers/net/cnxk/cnxk_ethdev.h
index 55da1da..6dad8ac 100644
--- a/drivers/net/cnxk/cnxk_ethdev.h
+++ b/drivers/net/cnxk/cnxk_ethdev.h
@@ -15,6 +15,9 @@ 
 
 #define CNXK_ETH_DEV_PMD_VERSION "1.0"
 
+/* Used for struct cnxk_eth_dev::flags */
+#define CNXK_LINK_CFG_IN_PROGRESS_F BIT_ULL(0)
+
 /* VLAN tag inserted by NIX_TX_VTAG_ACTION.
  * In Tx space is always reserved for this in FRS.
  */
@@ -181,6 +184,11 @@  int cnxk_nix_configure(struct rte_eth_dev *eth_dev);
 uint32_t cnxk_rss_ethdev_to_nix(struct cnxk_eth_dev *dev, uint64_t ethdev_rss,
 				uint8_t rss_level);
 
+/* Link */
+void cnxk_eth_dev_link_status_cb(struct roc_nix *nix,
+				 struct roc_nix_link_info *link);
+int cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete);
+
 /* Devargs */
 int cnxk_ethdev_parse_devargs(struct rte_devargs *devargs,
 			      struct cnxk_eth_dev *dev);
diff --git a/drivers/net/cnxk/cnxk_link.c b/drivers/net/cnxk/cnxk_link.c
new file mode 100644
index 0000000..0223d68
--- /dev/null
+++ b/drivers/net/cnxk/cnxk_link.c
@@ -0,0 +1,102 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include "cnxk_ethdev.h"
+
+static inline int
+nix_wait_for_link_cfg(struct cnxk_eth_dev *dev)
+{
+	uint16_t wait = 1000;
+
+	do {
+		rte_rmb();
+		if (!(dev->flags & CNXK_LINK_CFG_IN_PROGRESS_F))
+			break;
+		wait--;
+		rte_delay_ms(1);
+	} while (wait);
+
+	return wait ? 0 : -1;
+}
+
+static void
+nix_link_status_print(struct rte_eth_dev *eth_dev, struct rte_eth_link *link)
+{
+	if (link && link->link_status)
+		plt_info("Port %d: Link Up - speed %u Mbps - %s",
+			 (int)(eth_dev->data->port_id),
+			 (uint32_t)link->link_speed,
+			 link->link_duplex == ETH_LINK_FULL_DUPLEX
+				 ? "full-duplex"
+				 : "half-duplex");
+	else
+		plt_info("Port %d: Link Down", (int)(eth_dev->data->port_id));
+}
+
+void
+cnxk_eth_dev_link_status_cb(struct roc_nix *nix, struct roc_nix_link_info *link)
+{
+	struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
+	struct rte_eth_link eth_link;
+	struct rte_eth_dev *eth_dev;
+
+	if (!link || !nix)
+		return;
+
+	eth_dev = dev->eth_dev;
+	if (!eth_dev || !eth_dev->data->dev_conf.intr_conf.lsc)
+		return;
+
+	if (nix_wait_for_link_cfg(dev)) {
+		plt_err("Timeout waiting for link_cfg to complete");
+		return;
+	}
+
+	eth_link.link_status = link->status;
+	eth_link.link_speed = link->speed;
+	eth_link.link_autoneg = ETH_LINK_AUTONEG;
+	eth_link.link_duplex = link->full_duplex;
+
+	/* Print link info */
+	nix_link_status_print(eth_dev, &eth_link);
+
+	/* Update link info */
+	rte_eth_linkstatus_set(eth_dev, &eth_link);
+
+	/* Set the flag and execute application callbacks */
+	rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL);
+}
+
+int
+cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete)
+{
+	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	struct roc_nix_link_info info;
+	struct rte_eth_link link;
+	int rc;
+
+	RTE_SET_USED(wait_to_complete);
+	memset(&link, 0, sizeof(struct rte_eth_link));
+
+	if (roc_nix_is_sdp(&dev->nix))
+		return 0;
+
+	if (roc_nix_is_lbk(&dev->nix)) {
+		link.link_status = ETH_LINK_UP;
+		link.link_speed = ETH_SPEED_NUM_100G;
+		link.link_autoneg = ETH_LINK_FIXED;
+		link.link_duplex = ETH_LINK_FULL_DUPLEX;
+	} else {
+		rc = roc_nix_mac_link_info_get(&dev->nix, &info);
+		if (rc)
+			return rc;
+		link.link_status = info.status;
+		link.link_speed = info.speed;
+		link.link_autoneg = ETH_LINK_AUTONEG;
+		if (info.full_duplex)
+			link.link_duplex = info.full_duplex;
+	}
+
+	return rte_eth_linkstatus_set(eth_dev, &link);
+}
diff --git a/drivers/net/cnxk/meson.build b/drivers/net/cnxk/meson.build
index 45ccbe3..c0ec91a 100644
--- a/drivers/net/cnxk/meson.build
+++ b/drivers/net/cnxk/meson.build
@@ -10,7 +10,8 @@  endif
 
 sources = files('cnxk_ethdev.c',
 		'cnxk_ethdev_ops.c',
-		'cnxk_ethdev_devargs.c')
+		'cnxk_ethdev_devargs.c',
+		'cnxk_link.c')
 
 # CN9K
 sources += files('cn9k_ethdev.c')