]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
net: hns3: add support ethtool extended link state
authorGuangbin Huang <huangguangbin2@huawei.com>
Mon, 16 Aug 2021 02:15:29 +0000 (10:15 +0800)
committerJakub Kicinski <kuba@kernel.org>
Mon, 16 Aug 2021 22:12:14 +0000 (15:12 -0700)
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>
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c

index e0b7c3c44e7b4d1f7f9c5dd3e2297a470cb70772..848bed86619363dfbd1a1f093afb7b8c803e3f22 100644 (file)
@@ -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 {
index 167721b647adff95305094c94340914b957dafe0..8351050157630da2f59d804be755a6702ddcb204 100644 (file)
@@ -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)
index 2f186607c6e09030ae57317de7f5e3acc9cd60df..822d6fcbc73b8f6f871d43d00779e5d95e2ab34d 100644 (file)
@@ -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
index 18bde77ef944254c66f62606e194856b4e0b16c0..8e5be127909bd0defef907b39f5059d97f447636 100644 (file)
@@ -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
index 9fd15287986f12c259476557ab962db543eeea86..8779a63d51b393cff2404d945a8a583c43c3eb7c 100644 (file)
@@ -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 = {