net/cxgbe: add link up and down ops
authorRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Fri, 29 Jun 2018 19:23:51 +0000 (00:53 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 4 Jul 2018 20:52:21 +0000 (22:52 +0200)
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 <surendra@chelsio.com>

Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
drivers/net/cxgbe/cxgbe.h
drivers/net/cxgbe/cxgbe_ethdev.c
drivers/net/cxgbe/cxgbe_main.c
drivers/net/cxgbe/cxgbe_pfvf.h
drivers/net/cxgbe/cxgbevf_ethdev.c

index 27d6e2b..96a6a40 100644 (file)
 #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);
index a1dcf58..53ac7e2 100644 (file)
@@ -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,
index 08b2a42..c40a2d9 100644 (file)
@@ -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);
 }
 
 /*
index 2bba974..8d0a105 100644 (file)
@@ -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,
index a942ba6..b4770e0 100644 (file)
@@ -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,