From 265af08e75baa8534b1b14e9aeabb114d30b6194 Mon Sep 17 00:00:00 2001 From: Rahul Lakkireddy Date: Sat, 30 Jun 2018 00:53:51 +0530 Subject: [PATCH] net/cxgbe: add link up and down ops Add ops to set link up and down for both PF and VF. If wait_to_complete is set, poll for link update for up to 10 seconds max. Original work by Surendra Mobiya Signed-off-by: Rahul Lakkireddy --- drivers/net/cxgbe/cxgbe.h | 5 +++ drivers/net/cxgbe/cxgbe_ethdev.c | 72 ++++++++++++++++++++++++++++-- drivers/net/cxgbe/cxgbe_main.c | 36 ++++++++++----- drivers/net/cxgbe/cxgbe_pfvf.h | 2 + drivers/net/cxgbe/cxgbevf_ethdev.c | 2 + 5 files changed, 103 insertions(+), 14 deletions(-) diff --git a/drivers/net/cxgbe/cxgbe.h b/drivers/net/cxgbe/cxgbe.h index 27d6e2b84b..96a6a4084c 100644 --- a/drivers/net/cxgbe/cxgbe.h +++ b/drivers/net/cxgbe/cxgbe.h @@ -18,6 +18,10 @@ #define CXGBE_MIN_RX_BUFSIZE ETHER_MIN_MTU /* min buf size */ #define CXGBE_MAX_RX_PKTLEN (9000 + ETHER_HDR_LEN + ETHER_CRC_LEN) /* max pkt */ +/* Max poll time is 100 * 100msec = 10 sec */ +#define CXGBE_LINK_STATUS_POLL_MS 100 /* 100ms */ +#define CXGBE_LINK_STATUS_POLL_CNT 100 /* Max number of times to poll */ + #define CXGBE_DEFAULT_RSS_KEY_LEN 40 /* 320-bits */ #define CXGBE_RSS_HF_ALL (ETH_RSS_IPV4 | ETH_RSS_IPV6 | \ ETH_RSS_NONFRAG_IPV4_TCP | \ @@ -32,6 +36,7 @@ bool force_linkup(struct adapter *adap); int cxgbe_probe(struct adapter *adapter); int cxgbevf_probe(struct adapter *adapter); void cxgbe_get_speed_caps(struct port_info *pi, u32 *speed_caps); +int cxgbe_set_link_status(struct port_info *pi, bool status); int cxgbe_up(struct adapter *adap); int cxgbe_down(struct port_info *pi); void cxgbe_close(struct adapter *adapter); diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c index a1dcf58829..53ac7e2c2d 100644 --- a/drivers/net/cxgbe/cxgbe_ethdev.c +++ b/drivers/net/cxgbe/cxgbe_ethdev.c @@ -200,15 +200,27 @@ void cxgbe_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) } int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev, - __rte_unused int wait_to_complete) + int wait_to_complete) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; struct sge *s = &adapter->sge; struct rte_eth_link new_link = { 0 }; - unsigned int work_done, budget = 4; + unsigned int i, work_done, budget = 32; + u8 old_link = pi->link_cfg.link_ok; - cxgbe_poll(&s->fw_evtq, NULL, budget, &work_done); + for (i = 0; i < CXGBE_LINK_STATUS_POLL_CNT; i++) { + cxgbe_poll(&s->fw_evtq, NULL, budget, &work_done); + + /* Exit if link status changed or always forced up */ + if (pi->link_cfg.link_ok != old_link || force_linkup(adapter)) + break; + + if (!wait_to_complete) + break; + + rte_delay_ms(CXGBE_LINK_STATUS_POLL_MS); + } new_link.link_status = force_linkup(adapter) ? ETH_LINK_UP : pi->link_cfg.link_ok; @@ -219,6 +231,58 @@ int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev, return rte_eth_linkstatus_set(eth_dev, &new_link); } +/** + * Set device link up. + */ +int cxgbe_dev_set_link_up(struct rte_eth_dev *dev) +{ + struct port_info *pi = (struct port_info *)(dev->data->dev_private); + struct adapter *adapter = pi->adapter; + unsigned int work_done, budget = 32; + struct sge *s = &adapter->sge; + int ret; + + /* Flush all link events */ + cxgbe_poll(&s->fw_evtq, NULL, budget, &work_done); + + /* If link already up, nothing to do */ + if (pi->link_cfg.link_ok) + return 0; + + ret = cxgbe_set_link_status(pi, true); + if (ret) + return ret; + + cxgbe_dev_link_update(dev, 1); + return 0; +} + +/** + * Set device link down. + */ +int cxgbe_dev_set_link_down(struct rte_eth_dev *dev) +{ + struct port_info *pi = (struct port_info *)(dev->data->dev_private); + struct adapter *adapter = pi->adapter; + unsigned int work_done, budget = 32; + struct sge *s = &adapter->sge; + int ret; + + /* Flush all link events */ + cxgbe_poll(&s->fw_evtq, NULL, budget, &work_done); + + /* If link already down, nothing to do */ + if (!pi->link_cfg.link_ok) + return 0; + + ret = cxgbe_set_link_status(pi, false); + if (ret) + return ret; + + cxgbe_dev_link_update(dev, 0); + return 0; +} + int cxgbe_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); @@ -1035,6 +1099,8 @@ static const struct eth_dev_ops cxgbe_eth_dev_ops = { .dev_infos_get = cxgbe_dev_info_get, .dev_supported_ptypes_get = cxgbe_dev_supported_ptypes_get, .link_update = cxgbe_dev_link_update, + .dev_set_link_up = cxgbe_dev_set_link_up, + .dev_set_link_down = cxgbe_dev_set_link_down, .mtu_set = cxgbe_dev_mtu_set, .tx_queue_setup = cxgbe_dev_tx_queue_setup, .tx_queue_start = cxgbe_dev_tx_queue_start, diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c index 08b2a42d11..c40a2d9ad8 100644 --- a/drivers/net/cxgbe/cxgbe_main.c +++ b/drivers/net/cxgbe/cxgbe_main.c @@ -1572,6 +1572,30 @@ void cxgbe_get_speed_caps(struct port_info *pi, u32 *speed_caps) *speed_caps |= ETH_LINK_SPEED_FIXED; } +/** + * cxgbe_set_link_status - Set device link up or down. + * @pi: Underlying port's info + * @status: 0 - down, 1 - up + * + * Set the device link up or down. + */ +int cxgbe_set_link_status(struct port_info *pi, bool status) +{ + struct adapter *adapter = pi->adapter; + int err = 0; + + err = t4_enable_vi(adapter, adapter->mbox, pi->viid, status, status); + if (err) { + dev_err(adapter, "%s: disable_vi failed: %d\n", __func__, err); + return err; + } + + if (!status) + t4_reset_link_config(adapter, pi->pidx); + + return 0; +} + /** * cxgb_up - enable the adapter * @adap: adapter being enabled @@ -1597,17 +1621,7 @@ int cxgbe_up(struct adapter *adap) */ int cxgbe_down(struct port_info *pi) { - struct adapter *adapter = pi->adapter; - int err = 0; - - err = t4_enable_vi(adapter, adapter->mbox, pi->viid, false, false); - if (err) { - dev_err(adapter, "%s: disable_vi failed: %d\n", __func__, err); - return err; - } - - t4_reset_link_config(adapter, pi->pidx); - return 0; + return cxgbe_set_link_status(pi, false); } /* diff --git a/drivers/net/cxgbe/cxgbe_pfvf.h b/drivers/net/cxgbe/cxgbe_pfvf.h index 2bba974235..8d0a105aa1 100644 --- a/drivers/net/cxgbe/cxgbe_pfvf.h +++ b/drivers/net/cxgbe/cxgbe_pfvf.h @@ -35,6 +35,8 @@ int cxgbe_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu); int cxgbe_dev_start(struct rte_eth_dev *eth_dev); int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete); +int cxgbe_dev_set_link_up(struct rte_eth_dev *dev); +int cxgbe_dev_set_link_down(struct rte_eth_dev *dev); uint16_t cxgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); uint16_t cxgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, diff --git a/drivers/net/cxgbe/cxgbevf_ethdev.c b/drivers/net/cxgbe/cxgbevf_ethdev.c index a942ba6b65..b4770e0c59 100644 --- a/drivers/net/cxgbe/cxgbevf_ethdev.c +++ b/drivers/net/cxgbe/cxgbevf_ethdev.c @@ -85,6 +85,8 @@ static const struct eth_dev_ops cxgbevf_eth_dev_ops = { .dev_infos_get = cxgbe_dev_info_get, .dev_supported_ptypes_get = cxgbe_dev_supported_ptypes_get, .link_update = cxgbe_dev_link_update, + .dev_set_link_up = cxgbe_dev_set_link_up, + .dev_set_link_down = cxgbe_dev_set_link_down, .mtu_set = cxgbe_dev_mtu_set, .tx_queue_setup = cxgbe_dev_tx_queue_setup, .tx_queue_start = cxgbe_dev_tx_queue_start, -- 2.20.1