@@ -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);
@@ -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
@@ -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;
@@ -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;
}
@@ -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) \