From: Huisong Li <lihuis...@huawei.com>

This patch support flow control autoneg for fiber and backplane port.
And it depends on the capability of firmware.

Signed-off-by: Huisong Li <lihuis...@huawei.com>
Signed-off-by: Dongdong Liu <liudongdo...@huawei.com>
---
 drivers/net/hns3/hns3_cmd.c    | 30 +++++++++++++++++-
 drivers/net/hns3/hns3_cmd.h    | 20 +++++++++++-
 drivers/net/hns3/hns3_dump.c   |  1 +
 drivers/net/hns3/hns3_ethdev.c | 58 ++++++++--------------------------
 drivers/net/hns3/hns3_ethdev.h |  1 +
 5 files changed, 63 insertions(+), 47 deletions(-)

diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c
index d530650452..d0a3853656 100644
--- a/drivers/net/hns3/hns3_cmd.c
+++ b/drivers/net/hns3/hns3_cmd.c
@@ -428,7 +428,8 @@ hns3_get_caps_name(uint32_t caps_id)
                { HNS3_CAPS_UDP_TUNNEL_CSUM_B, "udp_tunnel_csum" },
                { HNS3_CAPS_RAS_IMP_B,         "ras_imp"         },
                { HNS3_CAPS_RXD_ADV_LAYOUT_B,  "rxd_adv_layout"  },
-               { HNS3_CAPS_TM_B,              "tm_capability"   }
+               { HNS3_CAPS_TM_B,              "tm_capability"   },
+               { HNS3_CAPS_FC_AUTO_B,         "fc_autoneg"      }
        };
        uint32_t i;
 
@@ -510,6 +511,8 @@ hns3_parse_capability(struct hns3_hw *hw,
                hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_RAS_IMP_B, 1);
        if (hns3_get_bit(caps, HNS3_CAPS_TM_B))
                hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_TM_B, 1);
+       if (hns3_get_bit(caps, HNS3_CAPS_FC_AUTO_B))
+               hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_FC_AUTO_B, 1);
 }
 
 static uint32_t
@@ -613,9 +616,31 @@ hns3_update_dev_lsc_cap(struct hns3_hw *hw, int 
fw_compact_cmd_result)
        }
 }
 
+static void
+hns3_set_fc_autoneg_cap(struct hns3_adapter *hns, int fw_compact_cmd_result)
+{
+       struct hns3_hw *hw = &hns->hw;
+       struct hns3_mac *mac = &hw->mac;
+
+       if (mac->media_type == HNS3_MEDIA_TYPE_COPPER) {
+               hns->pf.support_fc_autoneg = true;
+               return;
+       }
+
+       /*
+        * Flow control auto-negotiation requires the cooperation of the driver
+        * and firmware.
+        */
+       hns->pf.support_fc_autoneg = (hns3_dev_get_support(hw, FC_AUTO) &&
+                                       fw_compact_cmd_result == 0) ?
+                                       true : false;
+}
+
 static int
 hns3_apply_fw_compat_cmd_result(struct hns3_hw *hw, int result)
 {
+       struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+
        if (result != 0 && hns3_dev_get_support(hw, COPPER)) {
                hns3_err(hw, "firmware fails to initialize the PHY, ret = %d.",
                         result);
@@ -623,6 +648,7 @@ hns3_apply_fw_compat_cmd_result(struct hns3_hw *hw, int 
result)
        }
 
        hns3_update_dev_lsc_cap(hw, result);
+       hns3_set_fc_autoneg_cap(hns, result);
 
        return 0;
 }
@@ -642,6 +668,8 @@ hns3_firmware_compat_config(struct hns3_hw *hw, bool 
is_init)
                hns3_set_bit(compat, HNS3_NCSI_ERROR_REPORT_EN_B, 0);
                if (hns3_dev_get_support(hw, COPPER))
                        hns3_set_bit(compat, HNS3_FIRMWARE_PHY_DRIVER_EN_B, 1);
+               if (hns3_dev_get_support(hw, FC_AUTO))
+                       hns3_set_bit(compat, HNS3_MAC_FC_AUTONEG_EN_B, 1);
        }
        req->compat = rte_cpu_to_le_32(compat);
 
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 4abe0f1d13..d78c1b401e 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -323,6 +323,7 @@ enum HNS3_CAPS_BITS {
        HNS3_CAPS_RAS_IMP_B,
        HNS3_CAPS_RXD_ADV_LAYOUT_B = 15,
        HNS3_CAPS_TM_B = 19,
+       HNS3_CAPS_FC_AUTO_B = 30,
 };
 
 /* Capabilities of VF dependent on the PF */
@@ -666,6 +667,9 @@ enum hns3_promisc_type {
 #define HNS3_LINK_EVENT_REPORT_EN_B    0
 #define HNS3_NCSI_ERROR_REPORT_EN_B    1
 #define HNS3_FIRMWARE_PHY_DRIVER_EN_B  2
+
+#define HNS3_MAC_FC_AUTONEG_EN_B       6
+
 struct hns3_firmware_compat_cmd {
        uint32_t compat;
        uint8_t rsv[20];
@@ -680,6 +684,7 @@ struct hns3_firmware_compat_cmd {
 #define HNS3_PHY_LINK_MODE_AUTONEG_BIT         BIT(6)
 #define HNS3_PHY_LINK_MODE_PAUSE_BIT           BIT(13)
 #define HNS3_PHY_LINK_MODE_ASYM_PAUSE_BIT      BIT(14)
+#define HNS3_PHY_LINK_MODE_PAUSE_S             13
 
 #define HNS3_PHY_PARAM_CFG_BD_NUM      2
 struct hns3_phy_params_bd0_cmd {
@@ -789,6 +794,17 @@ struct hns3_sfp_type {
 #define HNS3_FIBER_LINK_SPEED_10M_BIT          BIT(7)
 #define HNS3_FIBER_LINK_SPEED_200G_BIT         BIT(8)
 
+/* Flags for pause status field */
+#define HNS3_FIBER_LOCAL_PAUSE_BIT     BIT(0)
+#define HNS3_FIBER_LOCAL_ASYM_PAUSE_BIT        BIT(1)
+#define HNS3_FIBER_LP_PAUSE_BIT                BIT(2)
+#define HNS3_FIBER_LP_ASYM_PAUSE_BIT   BIT(3)
+#define HNS3_FIBER_LOCAL_PAUSE_MASK    (HNS3_FIBER_LOCAL_PAUSE_BIT | \
+                                        HNS3_FIBER_LOCAL_ASYM_PAUSE_BIT)
+#define HNS3_FIBER_LP_PAUSE_MASK       (HNS3_FIBER_LP_PAUSE_BIT | \
+                                        HNS3_FIBER_LP_ASYM_PAUSE_BIT)
+#define HNS3_FIBER_LP_PAUSE_S          2
+
 struct hns3_sfp_info_cmd {
        uint32_t sfp_speed;
        uint8_t query_type; /* 0: sfp speed, 1: active */
@@ -798,7 +814,9 @@ struct hns3_sfp_info_cmd {
        uint8_t autoneg_ability;
        uint32_t supported_speed; /* speed supported by current media */
        uint32_t module_type;
-       uint8_t rsv1[8];
+       uint8_t rsv[2];
+       uint8_t pause_status;
+       uint8_t rsv1[5];
 };
 
 #define HNS3_MAC_CFG_FEC_AUTO_EN_B     0
diff --git a/drivers/net/hns3/hns3_dump.c b/drivers/net/hns3/hns3_dump.c
index 0af3c2ce09..c0839380ea 100644
--- a/drivers/net/hns3/hns3_dump.c
+++ b/drivers/net/hns3/hns3_dump.c
@@ -104,6 +104,7 @@ hns3_get_dev_feature_capability(FILE *file, struct hns3_hw 
*hw)
                {HNS3_DEV_SUPPORT_RAS_IMP_B, "RAS IMP"},
                {HNS3_DEV_SUPPORT_TM_B, "TM"},
                {HNS3_DEV_SUPPORT_VF_VLAN_FLT_MOD_B, "VF VLAN FILTER MOD"},
+               {HNS3_DEV_SUPPORT_FC_AUTO_B, "FC AUTO"}
        };
        uint32_t i;
 
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 8f819d5f23..5ef66f96c6 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -3975,6 +3975,7 @@ static int
 hns3_get_sfp_info(struct hns3_hw *hw, struct hns3_mac *mac_info)
 {
        struct hns3_sfp_info_cmd *resp;
+       uint32_t local_pause, lp_pause;
        struct hns3_cmd_desc desc;
        int ret;
 
@@ -4011,6 +4012,13 @@ hns3_get_sfp_info(struct hns3_hw *hw, struct hns3_mac 
*mac_info)
                mac_info->support_autoneg = resp->autoneg_ability;
                mac_info->link_autoneg = (resp->autoneg == 0) ? 
RTE_ETH_LINK_FIXED
                                        : RTE_ETH_LINK_AUTONEG;
+               local_pause = resp->pause_status & HNS3_FIBER_LOCAL_PAUSE_MASK;
+               lp_pause = (resp->pause_status & HNS3_FIBER_LP_PAUSE_MASK) >>
+                                               HNS3_FIBER_LP_PAUSE_S;
+               mac_info->advertising =
+                               local_pause << HNS3_PHY_LINK_MODE_PAUSE_S;
+               mac_info->lp_advertising =
+                               lp_pause << HNS3_PHY_LINK_MODE_PAUSE_S;
        } else {
                mac_info->query_type = HNS3_DEFAULT_QUERY;
        }
@@ -4093,6 +4101,8 @@ hns3_update_fiber_link_info(struct hns3_hw *hw)
                mac->supported_speed = mac_info.supported_speed;
                mac->support_autoneg = mac_info.support_autoneg;
                mac->link_autoneg = mac_info.link_autoneg;
+               mac->advertising = mac_info.advertising;
+               mac->lp_advertising = mac_info.lp_advertising;
 
                return 0;
        }
@@ -4495,24 +4505,6 @@ hns3_get_port_supported_speed(struct rte_eth_dev 
*eth_dev)
        return 0;
 }
 
-static void
-hns3_get_fc_autoneg_capability(struct hns3_adapter *hns)
-{
-       struct hns3_mac *mac = &hns->hw.mac;
-
-       if (mac->media_type == HNS3_MEDIA_TYPE_COPPER) {
-               hns->pf.support_fc_autoneg = true;
-               return;
-       }
-
-       /*
-        * Flow control auto-negotiation requires the cooperation of the driver
-        * and firmware. Currently, the optical port does not support flow
-        * control auto-negotiation.
-        */
-       hns->pf.support_fc_autoneg = false;
-}
-
 static int
 hns3_init_pf(struct rte_eth_dev *eth_dev)
 {
@@ -4615,8 +4607,6 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)
                goto err_supported_speed;
        }
 
-       hns3_get_fc_autoneg_capability(hns);
-
        hns3_tm_conf_init(eth_dev);
 
        return 0;
@@ -5181,8 +5171,7 @@ hns3_dev_close(struct rte_eth_dev *eth_dev)
 }
 
 static void
-hns3_get_autoneg_rxtx_pause_copper(struct hns3_hw *hw, bool *rx_pause,
-                                  bool *tx_pause)
+hns3_get_autoneg_rxtx_pause(struct hns3_hw *hw, bool *rx_pause, bool *tx_pause)
 {
        struct hns3_mac *mac = &hw->mac;
        uint32_t advertising = mac->advertising;
@@ -5193,8 +5182,7 @@ hns3_get_autoneg_rxtx_pause_copper(struct hns3_hw *hw, 
bool *rx_pause,
        if (advertising & lp_advertising & HNS3_PHY_LINK_MODE_PAUSE_BIT) {
                *rx_pause = true;
                *tx_pause = true;
-       } else if (advertising & lp_advertising &
-                  HNS3_PHY_LINK_MODE_ASYM_PAUSE_BIT) {
+       } else if (advertising & lp_advertising & 
HNS3_PHY_LINK_MODE_ASYM_PAUSE_BIT) {
                if (advertising & HNS3_PHY_LINK_MODE_PAUSE_BIT)
                        *rx_pause = true;
                else if (lp_advertising & HNS3_PHY_LINK_MODE_PAUSE_BIT)
@@ -5209,26 +5197,7 @@ hns3_get_autoneg_fc_mode(struct hns3_hw *hw)
        bool rx_pause = false;
        bool tx_pause = false;
 
-       switch (hw->mac.media_type) {
-       case HNS3_MEDIA_TYPE_COPPER:
-               hns3_get_autoneg_rxtx_pause_copper(hw, &rx_pause, &tx_pause);
-               break;
-
-       /*
-        * Flow control auto-negotiation is not supported for fiber and
-        * backplane media type.
-        */
-       case HNS3_MEDIA_TYPE_FIBER:
-       case HNS3_MEDIA_TYPE_BACKPLANE:
-               hns3_err(hw, "autoneg FC mode can't be obtained, but flow 
control auto-negotiation is enabled.");
-               current_mode = hw->requested_fc_mode;
-               goto out;
-       default:
-               hns3_err(hw, "autoneg FC mode can't be obtained for unknown 
media type(%u).",
-                        hw->mac.media_type);
-               current_mode = HNS3_FC_NONE;
-               goto out;
-       }
+       hns3_get_autoneg_rxtx_pause(hw, &rx_pause, &tx_pause);
 
        if (rx_pause && tx_pause)
                current_mode = HNS3_FC_FULL;
@@ -5239,7 +5208,6 @@ hns3_get_autoneg_fc_mode(struct hns3_hw *hw)
        else
                current_mode = HNS3_FC_NONE;
 
-out:
        return current_mode;
 }
 
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 8268dba788..88146f5054 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -892,6 +892,7 @@ enum hns3_dev_cap {
        HNS3_DEV_SUPPORT_RAS_IMP_B,
        HNS3_DEV_SUPPORT_TM_B,
        HNS3_DEV_SUPPORT_VF_VLAN_FLT_MOD_B,
+       HNS3_DEV_SUPPORT_FC_AUTO_B,
 };
 
 #define hns3_dev_get_support(hw, _name) \
-- 
2.22.0

Reply via email to