Add API to start device and periodic check of link state. 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/base/lio_hw_defs.h | 1 + drivers/net/liquidio/lio_ethdev.c | 108 ++++++++++++++++++++++++++++++++ drivers/net/liquidio/lio_ethdev.h | 8 +++ drivers/net/liquidio/lio_rxtx.c | 2 +- drivers/net/liquidio/lio_struct.h | 2 + 5 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/drivers/net/liquidio/base/lio_hw_defs.h b/drivers/net/liquidio/base/lio_hw_defs.h index ed6d90c..302a512 100644 --- a/drivers/net/liquidio/base/lio_hw_defs.h +++ b/drivers/net/liquidio/base/lio_hw_defs.h @@ -122,6 +122,7 @@ enum octeon_tag_type { /** LIO_OPCODE subcodes */ /* This subcode is sent by core PCI driver to indicate cores are ready. */ #define LIO_OPCODE_NW_DATA 0x02 /* network packet data */ +#define LIO_OPCODE_INFO 0x04 #define LIO_OPCODE_IF_CFG 0x09 #define LIO_MAX_RX_PKTLEN (64 * 1024) diff --git a/drivers/net/liquidio/lio_ethdev.c b/drivers/net/liquidio/lio_ethdev.c index e997e40..256e6b8 100644 --- a/drivers/net/liquidio/lio_ethdev.c +++ b/drivers/net/liquidio/lio_ethdev.c @@ -246,6 +246,113 @@ } } +/** + * Api to check link state. + */ +static void +lio_dev_get_link_status(struct rte_eth_dev *eth_dev) +{ + struct lio_device *lio_dev = LIO_DEV(eth_dev); + uint16_t timeout = LIO_MAX_CMD_TIMEOUT; + struct lio_link_status_resp *resp; + union octeon_link_status *ls; + struct lio_soft_command *sc; + uint32_t resp_size; + + if (!lio_dev->intf_open) + return; + + resp_size = sizeof(struct lio_link_status_resp); + sc = lio_alloc_soft_command(lio_dev, 0, resp_size, 0); + if (sc == NULL) + return; + + resp = (struct lio_link_status_resp *)sc->virtrptr; + lio_prepare_soft_command(lio_dev, sc, LIO_OPCODE, + LIO_OPCODE_INFO, 0, 0, 0); + + /* Setting wait time in seconds */ + sc->wait_time = LIO_MAX_CMD_TIMEOUT / 1000; + + if (lio_send_soft_command(lio_dev, sc) == LIO_IQ_SEND_FAILED) + goto get_status_fail; + + while ((*sc->status_word == LIO_COMPLETION_WORD_INIT) && --timeout) { + lio_flush_iq(lio_dev, lio_dev->instr_queue[sc->iq_no]); + rte_delay_ms(1); + } + + if (resp->status) + goto get_status_fail; + + ls = &resp->link_info.link; + + lio_swap_8B_data((uint64_t *)ls, sizeof(union octeon_link_status) >> 3); + + if (lio_dev->linfo.link.link_status64 != ls->link_status64) + lio_dev->linfo.link.link_status64 = ls->link_status64; + + lio_free_soft_command(sc); + + return; + +get_status_fail: + lio_free_soft_command(sc); +} + +/* This function will be invoked every LSC_TIMEOUT ns (100ms) + * and will update link state if it changes. + */ +static void +lio_sync_link_state_check(void *eth_dev) +{ + struct lio_device *lio_dev = + (((struct rte_eth_dev *)eth_dev)->data->dev_private); + + if (lio_dev->port_configured) + lio_dev_get_link_status(eth_dev); + + /* Schedule periodic link status check. + * Stop check if interface is close and start again while opening. + */ + if (lio_dev->intf_open) + rte_eal_alarm_set(LIO_LSC_TIMEOUT, lio_sync_link_state_check, + eth_dev); +} + +static int +lio_dev_start(struct rte_eth_dev *eth_dev) +{ + struct lio_device *lio_dev = LIO_DEV(eth_dev); + int ret = 0; + + lio_dev_info(lio_dev, "Starting port %d\n", eth_dev->data->port_id); + + if (lio_dev->fn_list.enable_io_queues(lio_dev)) + return -1; + + /* Ready for link status updates */ + lio_dev->intf_open = 1; + rte_mb(); + + /* start polling for lsc */ + ret = rte_eal_alarm_set(LIO_LSC_TIMEOUT, + lio_sync_link_state_check, + eth_dev); + if (ret) { + lio_dev_err(lio_dev, + "link state check handler creation failed\n"); + goto dev_lsc_handle_error; + } + + return 0; + +dev_lsc_handle_error: + lio_dev->intf_open = 0; + + return ret; +} + static int lio_dev_configure(struct rte_eth_dev *eth_dev) { struct lio_device *lio_dev = LIO_DEV(eth_dev); @@ -414,6 +521,7 @@ static int lio_dev_configure(struct rte_eth_dev *eth_dev) /* Define our ethernet definitions */ static const struct eth_dev_ops liovf_eth_dev_ops = { .dev_configure = lio_dev_configure, + .dev_start = lio_dev_start, .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 22e3d83..c7d3336 100644 --- a/drivers/net/liquidio/lio_ethdev.h +++ b/drivers/net/liquidio/lio_ethdev.h @@ -38,6 +38,8 @@ #include "lio_struct.h" +/* timeout to check link state updates from firmware in us */ +#define LIO_LSC_TIMEOUT 100000 /* 100000us (100ms) */ #define LIO_MAX_CMD_TIMEOUT 10000 /* 10000ms (10s) */ #define LIO_DEV(_eth_dev) ((_eth_dev)->data->dev_private) @@ -73,4 +75,10 @@ struct lio_if_cfg_resp { struct octeon_if_cfg_info cfg_info; uint64_t status; }; + +struct lio_link_status_resp { + uint64_t rh; + struct octeon_link_info link_info; + uint64_t status; +}; #endif /* _LIO_ETHDEV_H_ */ diff --git a/drivers/net/liquidio/lio_rxtx.c b/drivers/net/liquidio/lio_rxtx.c index edb1577..fe9a7f1 100644 --- a/drivers/net/liquidio/lio_rxtx.c +++ b/drivers/net/liquidio/lio_rxtx.c @@ -1587,7 +1587,7 @@ struct lio_soft_command * lio_dev = txq->lio_dev; iq_no = txq->txpciq.s.q_no; - if (!lio_dev->linfo.link.s.link_up) { + if (!lio_dev->intf_open || !lio_dev->linfo.link.s.link_up) { PMD_TX_LOG(lio_dev, ERR, "Transmit failed link_status : %d\n", lio_dev->linfo.link.s.link_up); goto xmit_failed; diff --git a/drivers/net/liquidio/lio_struct.h b/drivers/net/liquidio/lio_struct.h index de4c1f3..91a8fd2 100644 --- a/drivers/net/liquidio/lio_struct.h +++ b/drivers/net/liquidio/lio_struct.h @@ -569,6 +569,8 @@ struct lio_device { /** The state of this device */ rte_atomic64_t status; + uint8_t intf_open; + struct octeon_link_info linfo; uint8_t *hw_addr; -- 1.8.3.1