Every VF link previously followed the PF, so a VF could not be brought down
while the PF stayed up. Track vf_valid_status and combine it with the
physical link so the VF link can be set down independently.

A PF link-up event calls hinic3_set_vport_state(), which re-enables the
vport whenever the device is started, and that reports the link up again
after an administrative link down. Keep a separate admin_down flag, set
only by dev_set_link_up()/dev_set_link_down(), and check it both in
hinic3_set_vport_state() and when the VF link status is calculated.

Register the promiscuous callbacks in the VF eth_dev_ops so a VF can enter
promiscuous mode independently as well.

Signed-off-by: Jiacheng Ye <[email protected]>
---
 drivers/net/hinic3/base/hinic3_hwdev.h     |  3 +-
 drivers/net/hinic3/base/hinic3_nic_cfg.c   |  2 +
 drivers/net/hinic3/base/hinic3_nic_event.c |  9 +++-
 drivers/net/hinic3/hinic3_ethdev.c         | 53 +++++++++++++++++++++-
 drivers/net/hinic3/hinic3_ethdev.h         |  2 +
 5 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/drivers/net/hinic3/base/hinic3_hwdev.h 
b/drivers/net/hinic3/base/hinic3_hwdev.h
index c6661aa1a6..87ca18e571 100644
--- a/drivers/net/hinic3/base/hinic3_hwdev.h
+++ b/drivers/net/hinic3/base/hinic3_hwdev.h
@@ -157,7 +157,8 @@ struct hinic3_hwdev {
        char mgmt_ver[MGMT_VERSION_MAX_LEN];
 
        uint16_t max_vfs;
-       uint16_t link_status;
+       uint8_t link_status;
+       uint8_t vf_valid_status; /* vport_enable: 1, vport_disable: 0 */
        uint64_t features[HINIC3_MAX_FEATURE_QWORD];
 };
 
diff --git a/drivers/net/hinic3/base/hinic3_nic_cfg.c 
b/drivers/net/hinic3/base/hinic3_nic_cfg.c
index 2725f49df5..4a0e216b69 100644
--- a/drivers/net/hinic3/base/hinic3_nic_cfg.c
+++ b/drivers/net/hinic3/base/hinic3_nic_cfg.c
@@ -468,6 +468,8 @@ hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, bool 
enable)
                return -EIO;
        }
 
+       hwdev->vf_valid_status = enable;
+
        return 0;
 }
 
diff --git a/drivers/net/hinic3/base/hinic3_nic_event.c 
b/drivers/net/hinic3/base/hinic3_nic_event.c
index 981a5f5083..0fe7b54981 100644
--- a/drivers/net/hinic3/base/hinic3_nic_event.c
+++ b/drivers/net/hinic3/base/hinic3_nic_event.c
@@ -82,7 +82,8 @@ hinic3_set_vport_state(struct hinic3_hwdev *hwdev,
        nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(hwdev->eth_dev);
 
        if (link_state->state) {
-               if (hinic3_get_bit(HINIC3_DEV_START, &nic_dev->dev_status))
+               if (hinic3_get_bit(HINIC3_DEV_START, &nic_dev->dev_status) &&
+                   !nic_dev->admin_down)
                        err = hinic3_set_vport_enable(hwdev, true);
        } else {
                err = hinic3_set_vport_enable(hwdev, false);
@@ -111,6 +112,12 @@ link_status_event_handler(struct hinic3_hwdev *hwdev, 
struct hinic3_handler_info
 
        /* Link event reported only after set vport enable. */
        hinic3_get_link_port_info(hwdev, link_status->state, &link);
+
+       if (HINIC3_IS_VF(hwdev)) {
+               hwdev->link_status = link.link_status;
+               link.link_status = hwdev->link_status & hwdev->vf_valid_status;
+       }
+
        err = rte_eth_linkstatus_set(hwdev->eth_dev, &link);
        if (!err && hwdev->eth_dev->data->dev_conf.intr_conf.lsc != 0)
                rte_eth_dev_callback_process(hwdev->eth_dev,
diff --git a/drivers/net/hinic3/hinic3_ethdev.c 
b/drivers/net/hinic3/hinic3_ethdev.c
index 92393636c2..c3b2bf54eb 100644
--- a/drivers/net/hinic3/hinic3_ethdev.c
+++ b/drivers/net/hinic3/hinic3_ethdev.c
@@ -821,6 +821,26 @@ hinic3_fw_version_get(struct rte_eth_dev *dev, char 
*fw_version, size_t fw_size)
        return 0;
 }
 
+/**
+ * Get the VF link status reported to the application.
+ *
+ * @param[in] nic_dev
+ * Pointer to the hinic3 NIC device.
+ *
+ * @return
+ * Link status of the VF, RTE_ETH_LINK_UP or RTE_ETH_LINK_DOWN.
+ */
+static uint8_t
+hinic3_vf_link_status(struct hinic3_nic_dev *nic_dev)
+{
+       struct hinic3_hwdev *hwdev = nic_dev->hwdev;
+
+       if (nic_dev->admin_down)
+               return RTE_ETH_LINK_DOWN;
+
+       return hwdev->link_status & hwdev->vf_valid_status;
+}
+
 /**
  * Set ethernet device link state up.
  *
@@ -834,8 +854,11 @@ static int
 hinic3_dev_set_link_up(struct rte_eth_dev *dev)
 {
        struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+       struct rte_eth_link link = { 0 };
        int err;
 
+       nic_dev->admin_down = 0;
+
        /*
         * Vport enable will set function valid in mpu.
         * So dev start status need to be checked before vport enable.
@@ -858,6 +881,13 @@ hinic3_dev_set_link_up(struct rte_eth_dev *dev)
                return err;
        }
 
+       if (HINIC3_IS_VF(nic_dev->hwdev)) {
+               link = dev->data->dev_link;
+               link.link_status = hinic3_vf_link_status(nic_dev);
+
+               (void)rte_eth_linkstatus_set(dev, &link);
+       }
+
        return 0;
 }
 
@@ -874,8 +904,11 @@ static int
 hinic3_dev_set_link_down(struct rte_eth_dev *dev)
 {
        struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+       struct rte_eth_link link = { 0 };
        int err;
 
+       nic_dev->admin_down = 1;
+
        err = hinic3_set_vport_enable(nic_dev->hwdev, false);
        if (err) {
                PMD_DRV_LOG(ERR, "Disable vport failed, dev_name: %s",
@@ -887,11 +920,18 @@ hinic3_dev_set_link_down(struct rte_eth_dev *dev)
        err = hinic3_set_port_enable(nic_dev->hwdev, false);
        if (err) {
                PMD_DRV_LOG(ERR,
-                       "Set MAC link down failed, dev_name: %s, port_id: %d",
-                       nic_dev->dev_name, dev->data->port_id);
+                           "Set MAC link down failed, dev_name: %s, port_id: 
%d",
+                           nic_dev->dev_name, dev->data->port_id);
                return err;
        }
 
+       if (HINIC3_IS_VF(nic_dev->hwdev)) {
+               link = dev->data->dev_link;
+               link.link_status = hinic3_vf_link_status(nic_dev);
+
+               (void)rte_eth_linkstatus_set(dev, &link);
+       }
+
        return 0;
 }
 
@@ -939,6 +979,11 @@ hinic3_link_update(struct rte_eth_dev *dev, int 
wait_to_complete)
        } while (rep_cnt--);
 
 out:
+       if (HINIC3_IS_VF(nic_dev->hwdev)) {
+               nic_dev->hwdev->link_status = link.link_status;
+               link.link_status = hinic3_vf_link_status(nic_dev);
+       }
+
        return rte_eth_linkstatus_set(dev, &link);
 }
 
@@ -3661,6 +3706,8 @@ static const struct eth_dev_ops hinic3_pmd_vf_ops = {
        .dev_configure                 = hinic3_dev_configure,
        .dev_infos_get                 = hinic3_dev_infos_get,
        .fw_version_get                = hinic3_fw_version_get,
+       .dev_set_link_up               = hinic3_dev_set_link_up,
+       .dev_set_link_down             = hinic3_dev_set_link_down,
        .rx_queue_setup                = hinic3_rx_queue_setup,
        .tx_queue_setup                = hinic3_tx_queue_setup,
        .rx_queue_intr_enable          = hinic3_dev_rx_queue_intr_enable,
@@ -3682,6 +3729,8 @@ static const struct eth_dev_ops hinic3_pmd_vf_ops = {
        .vlan_offload_set              = hinic3_vlan_offload_set,
        .allmulticast_enable           = hinic3_dev_allmulticast_enable,
        .allmulticast_disable          = hinic3_dev_allmulticast_disable,
+       .promiscuous_enable            = hinic3_dev_promiscuous_enable,
+       .promiscuous_disable           = hinic3_dev_promiscuous_disable,
        .rss_hash_update               = hinic3_rss_hash_update,
        .rss_hash_conf_get             = hinic3_rss_conf_get,
        .reta_update                   = hinic3_rss_reta_update,
diff --git a/drivers/net/hinic3/hinic3_ethdev.h 
b/drivers/net/hinic3/hinic3_ethdev.h
index 935b7719ca..a078120794 100644
--- a/drivers/net/hinic3/hinic3_ethdev.h
+++ b/drivers/net/hinic3/hinic3_ethdev.h
@@ -141,6 +141,8 @@ struct hinic3_nic_dev {
 
        RTE_ATOMIC(uint64_t)dev_status;
 
+       uint8_t admin_down; /**< Link down requested by dev_set_link_down(). */
+
        uint8_t pause_set; /**< Flag of PAUSE frame setting. */
        struct nic_pause_config nic_pause;
 
-- 
2.33.0

Reply via email to