Signed-off-by: Shijith Thotton <shijith.thot...@caviumnetworks.com>
Signed-off-by: Jerin Jacob <jerin.ja...@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chick...@caviumnetworks.com>
Signed-off-by: Venkat Koppula <venkat.kopp...@caviumnetworks.com>
Signed-off-by: Mallesham Jatharakonda <mjatharako...@oneconvergence.com>
---
 drivers/net/liquidio/lio_ethdev.c | 76 ++++++++++++++++++++++++++++++++++++++-
 drivers/net/liquidio/lio_ethdev.h |  5 +++
 2 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/net/liquidio/lio_ethdev.c 
b/drivers/net/liquidio/lio_ethdev.c
index 256e6b8..299d28b 100644
--- a/drivers/net/liquidio/lio_ethdev.c
+++ b/drivers/net/liquidio/lio_ethdev.c
@@ -41,6 +41,32 @@
 #include "lio_ethdev.h"
 #include "lio_rxtx.h"
 
+/**
+ * Atomically writes the link status information into global
+ * structure rte_eth_dev.
+ *
+ * @param eth_dev
+ *   - Pointer to the structure rte_eth_dev to read from.
+ *   - Pointer to the buffer to be saved with the link status.
+ *
+ * @return
+ *   - On success, zero.
+ *   - On failure, negative value.
+ */
+static inline int
+lio_dev_atomic_write_link_status(struct rte_eth_dev *eth_dev,
+                                struct rte_eth_link *link)
+{
+       struct rte_eth_link *dst = &eth_dev->data->dev_link;
+       struct rte_eth_link *src = link;
+
+       if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
+                               *(uint64_t *)src) == 0)
+               return -1;
+
+       return 0;
+}
+
 static uint64_t
 lio_hweight64(uint64_t w)
 {
@@ -55,6 +81,49 @@
        return (res + (res >> 32)) & 0x00000000000000FFul;
 }
 
+static int
+lio_dev_link_update(struct rte_eth_dev *eth_dev,
+                   int wait_to_complete __rte_unused)
+{
+       struct lio_device *lio_dev = LIO_DEV(eth_dev);
+       struct rte_eth_link link, old;
+
+       /* Initialize */
+       link.link_status = ETH_LINK_DOWN;
+       link.link_speed = ETH_SPEED_NUM_NONE;
+       link.link_duplex = ETH_LINK_HALF_DUPLEX;
+       memset(&old, 0, sizeof(old));
+
+       /* Return what we found */
+       if (lio_dev->linfo.link.s.link_up == 0) {
+               /* Interface is down */
+               if (lio_dev_atomic_write_link_status(eth_dev, &link))
+                       return -1;
+               if (link.link_status == old.link_status)
+                       return -1;
+               return 0;
+       }
+
+       link.link_status = ETH_LINK_UP; /* Interface is up */
+       link.link_duplex = ETH_LINK_FULL_DUPLEX;
+       switch (lio_dev->linfo.link.s.speed) {
+       case LIO_LINK_SPEED_10000:
+               link.link_speed = ETH_SPEED_NUM_10G;
+               break;
+       default:
+               link.link_speed = ETH_SPEED_NUM_NONE;
+               link.link_duplex = ETH_LINK_HALF_DUPLEX;
+       }
+
+       if (lio_dev_atomic_write_link_status(eth_dev, &link))
+               return -1;
+
+       if (link.link_status == old.link_status)
+               return -1;
+
+       return 0;
+}
+
 /**
  * Setup our receive queue/ringbuffer. This is the
  * queue the Octeon uses to send us packets and
@@ -289,8 +358,10 @@
 
        lio_swap_8B_data((uint64_t *)ls, sizeof(union octeon_link_status) >> 3);
 
-       if (lio_dev->linfo.link.link_status64 != ls->link_status64)
+       if (lio_dev->linfo.link.link_status64 != ls->link_status64) {
                lio_dev->linfo.link.link_status64 = ls->link_status64;
+               lio_dev_link_update(eth_dev, 0);
+       }
 
        lio_free_soft_command(sc);
 
@@ -495,6 +566,8 @@ static int lio_dev_configure(struct rte_eth_dev *eth_dev)
                return -ENOMEM;
        }
 
+       lio_dev_link_update(eth_dev, 0);
+
        lio_dev->port_configured = 1;
 
        lio_free_soft_command(sc);
@@ -522,6 +595,7 @@ static int lio_dev_configure(struct rte_eth_dev *eth_dev)
 static const struct eth_dev_ops liovf_eth_dev_ops = {
        .dev_configure          = lio_dev_configure,
        .dev_start              = lio_dev_start,
+       .link_update            = lio_dev_link_update,
        .rx_queue_setup         = lio_dev_rx_queue_setup,
        .rx_queue_release       = lio_dev_rx_queue_release,
        .tx_queue_setup         = lio_dev_tx_queue_setup,
diff --git a/drivers/net/liquidio/lio_ethdev.h 
b/drivers/net/liquidio/lio_ethdev.h
index c7d3336..98ff493 100644
--- a/drivers/net/liquidio/lio_ethdev.h
+++ b/drivers/net/liquidio/lio_ethdev.h
@@ -44,6 +44,11 @@
 
 #define LIO_DEV(_eth_dev)              ((_eth_dev)->data->dev_private)
 
+enum lio_bus_speed {
+       LIO_LINK_SPEED_UNKNOWN  = 0,
+       LIO_LINK_SPEED_10000    = 10000
+};
+
 struct octeon_if_cfg_info {
        uint64_t iqmask;        /** mask for IQs enabled for the port */
        uint64_t oqmask;        /** mask for OQs enabled for the port */
-- 
1.8.3.1

Reply via email to