248 lines
9.2 KiB
Diff
248 lines
9.2 KiB
Diff
From 88a0023ce8e2fd3c7cc21032690517968fee03f6 Mon Sep 17 00:00:00 2001
|
|
From: Guangbin Huang <huangguangbin2@huawei.com>
|
|
Date: Sat, 21 Aug 2021 17:00:41 +0800
|
|
Subject: [PATCH 101/283] net: hns3: add support ethtool extended link state
|
|
|
|
mainline inclusion
|
|
from mainline-v5.15-rc1
|
|
commit f5c2b9f0fc078308a88de807d60cd4e352a165fc
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EMYT
|
|
CVE: NA
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f5c2b9f0fc078308a88de807d60cd4e352a165fc
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
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: Guangbin Huang <huangguangbin2@huawei.com>
|
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
Reviewed-by: Yongxin Li <liyongxin1@huawei.com>
|
|
Signed-off-by: Junxin Chen <chenjunxin1@huawei.com>
|
|
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
|
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>
|
|
|
|
Conflicts:
|
|
drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
---
|
|
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 +
|
|
.../ethernet/hisilicon/hns3/hns3_ethtool.c | 66 +++++++++++++++++++
|
|
.../ethernet/hisilicon/hns3/hns3_ethtool.h | 6 ++
|
|
.../hisilicon/hns3/hns3pf/hclge_cmd.h | 3 +
|
|
.../hisilicon/hns3/hns3pf/hclge_main.c | 24 +++++++
|
|
include/linux/ethtool.h | 19 ++++++
|
|
6 files changed, 120 insertions(+)
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
index 58022716456d..918b86a9cf88 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
@@ -729,6 +729,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);
|
|
/* Notice! If the function is not for test, the definition must before
|
|
* CONFIG_HNS3_TEST! Because RoCE will use this head file, and it won't
|
|
* set CONFIG_HNS3_TEST, that may cause RoCE calling the wrong function.
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
index d4d5474d0f09..1c3d3036de35 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
@@ -1723,6 +1723,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,
|
|
@@ -1794,6 +1859,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)
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.h b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.h
|
|
index 2f186607c6e0..822d6fcbc73b 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.h
|
|
@@ -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
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
index 75cf58c5f0b3..5daf24ca0e4e 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
@@ -321,6 +321,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
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
index 359c6fc4ca1d..480519de4992 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
@@ -12028,6 +12028,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;
|
|
+}
|
|
+
|
|
struct hnae3_ae_ops hclge_ops = {
|
|
.init_ae_dev = hclge_init_ae_dev,
|
|
.uninit_ae_dev = hclge_uninit_ae_dev,
|
|
@@ -12129,6 +12152,7 @@ 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 = {
|
|
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
|
|
index 65c244c2dc97..4154522d8497 100644
|
|
--- a/include/linux/ethtool.h
|
|
+++ b/include/linux/ethtool.h
|
|
@@ -87,6 +87,21 @@ struct net_device;
|
|
u32 ethtool_op_get_link(struct net_device *dev);
|
|
int ethtool_op_get_ts_info(struct net_device *dev, struct ethtool_ts_info *eti);
|
|
|
|
+/**
|
|
+ * struct ethtool_link_ext_state_info - link extended state and substate.
|
|
+ */
|
|
+struct ethtool_link_ext_state_info {
|
|
+ enum ethtool_link_ext_state link_ext_state;
|
|
+ union {
|
|
+ enum ethtool_link_ext_substate_autoneg autoneg;
|
|
+ enum ethtool_link_ext_substate_link_training link_training;
|
|
+ enum ethtool_link_ext_substate_link_logical_mismatch link_logical_mismatch;
|
|
+ enum ethtool_link_ext_substate_bad_signal_integrity bad_signal_integrity;
|
|
+ enum ethtool_link_ext_substate_cable_issue cable_issue;
|
|
+ u8 __link_ext_substate;
|
|
+ };
|
|
+};
|
|
+
|
|
/**
|
|
* ethtool_rxfh_indir_default - get default value for RX flow hash indirection
|
|
* @index: Index in RX flow hash indirection table
|
|
@@ -381,6 +396,10 @@ struct ethtool_ops {
|
|
void (*set_msglevel)(struct net_device *, u32);
|
|
int (*nway_reset)(struct net_device *);
|
|
u32 (*get_link)(struct net_device *);
|
|
+#ifndef __GENKSYMS__
|
|
+ int (*get_link_ext_state)(struct net_device *,
|
|
+ struct ethtool_link_ext_state_info *);
|
|
+#endif
|
|
int (*get_eeprom_len)(struct net_device *);
|
|
int (*get_eeprom)(struct net_device *,
|
|
struct ethtool_eeprom *, u8 *);
|
|
--
|
|
2.34.1
|
|
|