Commit fd04ed1c authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'net-hns3-add-support-ethtool-extended-link-state'

Guangbin Huang says:

====================
net: hns3: add support ethtool extended link state

This series adds support for ethtool extended link state in the HNS3
ethernet driver to add one additional information for user to know
why a link is not up.
====================

Link: https://lore.kernel.org/r/1629080129-46507-1-git-send-email-huangguangbin2@huawei.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 1b3f78df f5c2b9f0
......@@ -595,6 +595,14 @@ Link extended substates:
that is not formally
supported, which led to
signal integrity issues
``ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_REFERENCE_CLOCK_LOST`` The external clock signal for
SerDes is too weak or
unavailable.
``ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_ALOS`` The received signal for
SerDes is too weak because
analog loss of signal.
================================================================= =============================
Cable issue substates:
......
......@@ -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 {
......
......@@ -7,21 +7,7 @@
#include <linux/sfp.h>
#include "hns3_enet.h"
struct hns3_stats {
char stats_string[ETH_GSTRING_LEN];
int stats_offset;
};
struct hns3_sfp_type {
u8 type;
u8 ext_type;
};
struct hns3_pflag_desc {
char name[ETH_GSTRING_LEN];
void (*handler)(struct net_device *netdev, bool enable);
};
#include "hns3_ethtool.h"
/* tqp related stats */
#define HNS3_TQP_STAT(_string, _member) { \
......@@ -1725,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,
......@@ -1796,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)
......
/* SPDX-License-Identifier: GPL-2.0+ */
// Copyright (c) 2021 Hisilicon Limited.
#ifndef __HNS3_ETHTOOL_H
#define __HNS3_ETHTOOL_H
#include <linux/ethtool.h>
#include <linux/netdevice.h>
struct hns3_stats {
char stats_string[ETH_GSTRING_LEN];
int stats_offset;
};
struct hns3_sfp_type {
u8 type;
u8 ext_type;
};
struct hns3_pflag_desc {
char name[ETH_GSTRING_LEN];
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 = {
......
......@@ -639,6 +639,8 @@ enum ethtool_link_ext_substate_link_logical_mismatch {
enum ethtool_link_ext_substate_bad_signal_integrity {
ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1,
ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE,
ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_REFERENCE_CLOCK_LOST,
ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_ALOS,
};
/* More information in addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. */
......
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