Commit f5c2b9f0 authored by Guangbin Huang's avatar Guangbin Huang Committed by Jakub Kicinski

net: hns3: add support ethtool extended link state

In order to know the reason of link up failure, add supporting ethtool
extended link state. Driver reads the link status code from firmware if
in link down state and converts it to ethtool extended link state.
Signed-off-by: default avatarGuangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent edb40bbc
......@@ -718,6 +718,8 @@ struct hnae3_ae_ops {
u32 nsec, u32 sec);
int (*get_ts_info)(struct hnae3_handle *handle,
struct ethtool_ts_info *info);
int (*get_link_diagnosis_info)(struct hnae3_handle *handle,
u32 *status_code);
};
struct hnae3_dcb_ops {
......
......@@ -1711,6 +1711,71 @@ static int hns3_get_ts_info(struct net_device *netdev,
return ethtool_op_get_ts_info(netdev, info);
}
static const struct hns3_ethtool_link_ext_state_mapping
hns3_link_ext_state_map[] = {
{1, ETHTOOL_LINK_EXT_STATE_AUTONEG,
ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD},
{2, ETHTOOL_LINK_EXT_STATE_AUTONEG,
ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED},
{256, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT},
{257, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY},
{512, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT},
{513, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK},
{514, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED},
{515, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED},
{768, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS},
{769, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_REFERENCE_CLOCK_LOST},
{770, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_ALOS},
{1024, ETHTOOL_LINK_EXT_STATE_NO_CABLE, 0},
{1025, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
{1026, ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, 0},
};
static int hns3_get_link_ext_state(struct net_device *netdev,
struct ethtool_link_ext_state_info *info)
{
const struct hns3_ethtool_link_ext_state_mapping *map;
struct hnae3_handle *h = hns3_get_handle(netdev);
u32 status_code, i;
int ret;
if (netif_carrier_ok(netdev))
return -ENODATA;
if (!h->ae_algo->ops->get_link_diagnosis_info)
return -EOPNOTSUPP;
ret = h->ae_algo->ops->get_link_diagnosis_info(h, &status_code);
if (ret)
return ret;
for (i = 0; i < ARRAY_SIZE(hns3_link_ext_state_map); i++) {
map = &hns3_link_ext_state_map[i];
if (map->status_code == status_code) {
info->link_ext_state = map->link_ext_state;
info->__link_ext_substate = map->link_ext_substate;
return 0;
}
}
return -ENODATA;
}
static const struct ethtool_ops hns3vf_ethtool_ops = {
.supported_coalesce_params = HNS3_ETHTOOL_COALESCE,
.get_drvinfo = hns3_get_drvinfo,
......@@ -1782,6 +1847,7 @@ static const struct ethtool_ops hns3_ethtool_ops = {
.get_tunable = hns3_get_tunable,
.set_tunable = hns3_set_tunable,
.reset = hns3_set_reset,
.get_link_ext_state = hns3_get_link_ext_state,
};
void hns3_ethtool_set_ops(struct net_device *netdev)
......
......@@ -22,4 +22,10 @@ struct hns3_pflag_desc {
void (*handler)(struct net_device *netdev, bool enable);
};
struct hns3_ethtool_link_ext_state_mapping {
u32 status_code;
enum ethtool_link_ext_state link_ext_state;
u8 link_ext_substate;
};
#endif
......@@ -316,6 +316,9 @@ enum hclge_opcode_type {
/* PHY command */
HCLGE_OPC_PHY_LINK_KSETTING = 0x7025,
HCLGE_OPC_PHY_REG = 0x7026,
/* Query link diagnosis info command */
HCLGE_OPC_QUERY_LINK_DIAGNOSIS = 0x702A,
};
#define HCLGE_TQP_REG_OFFSET 0x80000
......
......@@ -12843,6 +12843,29 @@ static int hclge_get_module_eeprom(struct hnae3_handle *handle, u32 offset,
return 0;
}
static int hclge_get_link_diagnosis_info(struct hnae3_handle *handle,
u32 *status_code)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret;
if (hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2)
return -EOPNOTSUPP;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_LINK_DIAGNOSIS, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"failed to query link diagnosis info, ret = %d\n", ret);
return ret;
}
*status_code = le32_to_cpu(desc.data[0]);
return 0;
}
static const struct hnae3_ae_ops hclge_ops = {
.init_ae_dev = hclge_init_ae_dev,
.uninit_ae_dev = hclge_uninit_ae_dev,
......@@ -12943,6 +12966,7 @@ static const struct hnae3_ae_ops hclge_ops = {
.set_tx_hwts_info = hclge_ptp_set_tx_info,
.get_rx_hwts = hclge_ptp_get_rx_hwts,
.get_ts_info = hclge_ptp_get_ts_info,
.get_link_diagnosis_info = hclge_get_link_diagnosis_info,
};
static struct hnae3_ae_algo ae_algo = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment