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 = ð_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