414 lines
14 KiB
Diff
414 lines
14 KiB
Diff
From aec0faec2bfbd8d5a18f52d1778519911fdb3831 Mon Sep 17 00:00:00 2001
|
|
From: Guangbin Huang <huangguangbin2@huawei.com>
|
|
Date: Sat, 24 Jul 2021 15:43:48 +0800
|
|
Subject: [PATCH 056/283] net: hns3: add support for imp-controlled PHYs
|
|
|
|
mainline inclusion
|
|
from mainline-v5.13-rc1
|
|
commit f5f2b3e4dcc0e944dc33b522df84576679fbd8eb
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EMQV
|
|
CVE: NA
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f5f2b3e4dcc0e944dc33b522df84576679fbd8eb
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
IMP(Intelligent Management Processor) firmware add a new feature
|
|
to take control of PHYs for some new devices, PF driver adds
|
|
support for this feature.
|
|
|
|
Driver queries device's capability to check whether IMP supports
|
|
this feature, it will tell IMP to enable this feature by firmware
|
|
compatible command if it is supported.
|
|
|
|
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
|
|
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
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/hns3_debugfs.c
|
|
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
|
|
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
---
|
|
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 7 +-
|
|
.../ethernet/hisilicon/hns3/hns3_ethtool.c | 9 +-
|
|
.../hisilicon/hns3/hns3pf/hclge_cmd.c | 4 +
|
|
.../hisilicon/hns3/hns3pf/hclge_cmd.h | 50 ++++++
|
|
.../hisilicon/hns3/hns3pf/hclge_main.c | 149 +++++++++++++++++-
|
|
include/uapi/linux/ethtool.h | 8 +-
|
|
6 files changed, 222 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
index 0ffb8109fba9..99fe5603ef1c 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
@@ -89,6 +89,8 @@ enum HNAE3_DEV_CAP_BITS {
|
|
HNAE3_DEV_SUPPORT_TQP_TXRX_INDEP_B,
|
|
HNAE3_DEV_SUPPORT_HW_PAD_B,
|
|
HNAE3_DEV_SUPPORT_STASH_B,
|
|
+ HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B,
|
|
+ HNAE3_DEV_SUPPORT_PAUSE_B,
|
|
};
|
|
|
|
#define hnae3_dev_fd_supported(hdev) \
|
|
@@ -680,7 +682,10 @@ struct hnae3_ae_ops {
|
|
int (*get_module_eeprom)(struct hnae3_handle *handle, u32 offset,
|
|
u32 len, u8 *data);
|
|
bool (*get_cmdq_stat)(struct hnae3_handle *handle);
|
|
-
|
|
+ int (*get_phy_link_ksettings)(struct hnae3_handle *handle,
|
|
+ struct ethtool_link_ksettings *cmd);
|
|
+ int (*set_phy_link_ksettings)(struct hnae3_handle *handle,
|
|
+ const struct ethtool_link_ksettings *cmd);
|
|
/* 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 2eb3aac3c711..3bad65d1a49d 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
@@ -671,6 +671,7 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
|
|
struct ethtool_link_ksettings *cmd)
|
|
{
|
|
struct hnae3_handle *h = hns3_get_handle(netdev);
|
|
+ struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
|
|
const struct hnae3_ae_ops *ops;
|
|
u8 module_type;
|
|
u8 media_type;
|
|
@@ -701,7 +702,10 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
|
|
break;
|
|
case HNAE3_MEDIA_TYPE_COPPER:
|
|
cmd->base.port = PORT_TP;
|
|
- if (!netdev->phydev)
|
|
+ if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) &&
|
|
+ ops->get_phy_link_ksettings)
|
|
+ ops->get_phy_link_ksettings(h, cmd);
|
|
+ else if (!netdev->phydev)
|
|
hns3_get_ksettings(h, cmd);
|
|
else
|
|
phy_ethtool_ksettings_get(netdev->phydev, cmd);
|
|
@@ -796,6 +800,9 @@ static int hns3_set_link_ksettings(struct net_device *netdev,
|
|
return -EINVAL;
|
|
|
|
return phy_ethtool_ksettings_set(netdev->phydev, cmd);
|
|
+ } else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) &&
|
|
+ ops->set_phy_link_ksettings) {
|
|
+ return ops->set_phy_link_ksettings(handle, cmd);
|
|
}
|
|
|
|
if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
|
|
index 64476a2629ba..c4d30bcc8fa3 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
|
|
@@ -390,6 +390,8 @@ static void hclge_parse_capability(struct hclge_dev *hdev,
|
|
set_bit(HNAE3_DEV_SUPPORT_TQP_TXRX_INDEP_B, ae_dev->caps);
|
|
if (hnae3_get_bit(caps, HCLGE_CAP_HW_TX_CSUM_B))
|
|
set_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps);
|
|
+ if (hnae3_get_bit(caps, HCLGE_CAP_PHY_IMP_B))
|
|
+ set_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps);
|
|
}
|
|
|
|
static enum hclge_cmd_status
|
|
@@ -476,6 +478,8 @@ static int hclge_firmware_compat_config(struct hclge_dev *hdev, bool en)
|
|
|
|
hnae3_set_bit(compat, HCLGE_LINK_EVENT_REPORT_EN_B, 1);
|
|
hnae3_set_bit(compat, HCLGE_NCSI_ERROR_REPORT_EN_B, 1);
|
|
+ if (hnae3_dev_phy_imp_supported(hdev))
|
|
+ hnae3_set_bit(compat, HCLGE_PHY_IMP_EN_B, 1);
|
|
req->compat = cpu_to_le32(compat);
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
index e6727366028e..2922cd1bc859 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
@@ -308,6 +308,9 @@ enum hclge_opcode_type {
|
|
HCLGE_PPP_MAC_VLAN_IDX_RD = 0x2104,
|
|
HCLGE_MAC_ETHERTYPE_IDX_RD = 0x2105,
|
|
HCLGE_NCSI_INT_EN = 0x2401,
|
|
+
|
|
+ /* PHY command */
|
|
+ HCLGE_OPC_PHY_LINK_KSETTING = 0x7025,
|
|
};
|
|
|
|
#define HCLGE_TQP_REG_OFFSET 0x80000
|
|
@@ -1107,6 +1110,7 @@ struct hclge_query_ppu_pf_other_int_dfx_cmd {
|
|
|
|
#define HCLGE_LINK_EVENT_REPORT_EN_B 0
|
|
#define HCLGE_NCSI_ERROR_REPORT_EN_B 1
|
|
+#define HCLGE_PHY_IMP_EN_B 2
|
|
struct hclge_firmware_compat_cmd {
|
|
__le32 compat;
|
|
u8 rsv[20];
|
|
@@ -1125,6 +1129,52 @@ struct hclge_sfp_info_bd0_cmd {
|
|
u8 data[HCLGE_SFP_INFO_BD0_LEN];
|
|
};
|
|
|
|
+#define HCLGE_QUERY_DEV_SPECS_BD_NUM 4
|
|
+
|
|
+struct hclge_dev_specs_0_cmd {
|
|
+ __le32 rsv0;
|
|
+ __le32 mac_entry_num;
|
|
+ __le32 mng_entry_num;
|
|
+ __le16 rss_ind_tbl_size;
|
|
+ __le16 rss_key_size;
|
|
+ __le16 int_ql_max;
|
|
+ u8 max_non_tso_bd_num;
|
|
+ u8 rsv1;
|
|
+ __le32 max_tm_rate;
|
|
+};
|
|
+
|
|
+#define HCLGE_DEF_MAX_INT_GL 0x1FE0U
|
|
+
|
|
+struct hclge_dev_specs_1_cmd {
|
|
+ __le16 max_frm_size;
|
|
+ __le16 max_qset_num;
|
|
+ __le16 max_int_gl;
|
|
+ u8 rsv1[18];
|
|
+};
|
|
+
|
|
+#define HCLGE_PHY_LINK_SETTING_BD_NUM 2
|
|
+
|
|
+struct hclge_phy_link_ksetting_0_cmd {
|
|
+ __le32 speed;
|
|
+ u8 duplex;
|
|
+ u8 autoneg;
|
|
+ u8 eth_tp_mdix;
|
|
+ u8 eth_tp_mdix_ctrl;
|
|
+ u8 port;
|
|
+ u8 transceiver;
|
|
+ u8 phy_address;
|
|
+ u8 rsv;
|
|
+ __le32 supported;
|
|
+ __le32 advertising;
|
|
+ __le32 lp_advertising;
|
|
+};
|
|
+
|
|
+struct hclge_phy_link_ksetting_1_cmd {
|
|
+ u8 master_slave_cfg;
|
|
+ u8 master_slave_state;
|
|
+ u8 rsv[22];
|
|
+};
|
|
+
|
|
int hclge_cmd_init(struct hclge_dev *hdev);
|
|
static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value)
|
|
{
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
index 986d9e5acb3b..115e70fcce36 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
@@ -2903,6 +2903,141 @@ static int hclge_get_sfp_info(struct hclge_dev *hdev, struct hclge_mac *mac)
|
|
return 0;
|
|
}
|
|
|
|
+static int hclge_get_phy_link_ksettings(struct hnae3_handle *handle,
|
|
+ struct ethtool_link_ksettings *cmd)
|
|
+{
|
|
+ struct hclge_desc desc[HCLGE_PHY_LINK_SETTING_BD_NUM];
|
|
+ struct hclge_vport *vport = hclge_get_vport(handle);
|
|
+ struct hclge_phy_link_ksetting_0_cmd *req0;
|
|
+ struct hclge_phy_link_ksetting_1_cmd *req1;
|
|
+ u32 supported, advertising, lp_advertising;
|
|
+ struct hclge_dev *hdev = vport->back;
|
|
+ int ret;
|
|
+
|
|
+ hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_PHY_LINK_KSETTING,
|
|
+ true);
|
|
+ desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
|
|
+ hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_PHY_LINK_KSETTING,
|
|
+ true);
|
|
+
|
|
+ ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_PHY_LINK_SETTING_BD_NUM);
|
|
+ if (ret) {
|
|
+ dev_err(&hdev->pdev->dev,
|
|
+ "failed to get phy link ksetting, ret = %d.\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ req0 = (struct hclge_phy_link_ksetting_0_cmd *)desc[0].data;
|
|
+ cmd->base.autoneg = req0->autoneg;
|
|
+ cmd->base.speed = le32_to_cpu(req0->speed);
|
|
+ cmd->base.duplex = req0->duplex;
|
|
+ cmd->base.port = req0->port;
|
|
+ cmd->base.transceiver = req0->transceiver;
|
|
+ cmd->base.phy_address = req0->phy_address;
|
|
+ cmd->base.eth_tp_mdix = req0->eth_tp_mdix;
|
|
+ cmd->base.eth_tp_mdix_ctrl = req0->eth_tp_mdix_ctrl;
|
|
+ supported = le32_to_cpu(req0->supported);
|
|
+ advertising = le32_to_cpu(req0->advertising);
|
|
+ lp_advertising = le32_to_cpu(req0->lp_advertising);
|
|
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
|
|
+ supported);
|
|
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
|
|
+ advertising);
|
|
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising,
|
|
+ lp_advertising);
|
|
+
|
|
+ req1 = (struct hclge_phy_link_ksetting_1_cmd *)desc[1].data;
|
|
+ cmd->base.master_slave_cfg = req1->master_slave_cfg;
|
|
+ cmd->base.master_slave_state = req1->master_slave_state;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
|
|
+ const struct ethtool_link_ksettings *cmd)
|
|
+{
|
|
+ struct hclge_desc desc[HCLGE_PHY_LINK_SETTING_BD_NUM];
|
|
+ struct hclge_vport *vport = hclge_get_vport(handle);
|
|
+ struct hclge_phy_link_ksetting_0_cmd *req0;
|
|
+ struct hclge_phy_link_ksetting_1_cmd *req1;
|
|
+ struct hclge_dev *hdev = vport->back;
|
|
+ u32 advertising;
|
|
+ int ret;
|
|
+
|
|
+ if (cmd->base.autoneg == AUTONEG_DISABLE &&
|
|
+ ((cmd->base.speed != SPEED_100 && cmd->base.speed != SPEED_10) ||
|
|
+ (cmd->base.duplex != DUPLEX_HALF &&
|
|
+ cmd->base.duplex != DUPLEX_FULL)))
|
|
+ return -EINVAL;
|
|
+
|
|
+ hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_PHY_LINK_KSETTING,
|
|
+ false);
|
|
+ desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
|
|
+ hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_PHY_LINK_KSETTING,
|
|
+ false);
|
|
+
|
|
+ req0 = (struct hclge_phy_link_ksetting_0_cmd *)desc[0].data;
|
|
+ req0->autoneg = cmd->base.autoneg;
|
|
+ req0->speed = cpu_to_le32(cmd->base.speed);
|
|
+ req0->duplex = cmd->base.duplex;
|
|
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
|
|
+ cmd->link_modes.advertising);
|
|
+ req0->advertising = cpu_to_le32(advertising);
|
|
+ req0->eth_tp_mdix_ctrl = cmd->base.eth_tp_mdix_ctrl;
|
|
+
|
|
+ req1 = (struct hclge_phy_link_ksetting_1_cmd *)desc[1].data;
|
|
+ req1->master_slave_cfg = cmd->base.master_slave_cfg;
|
|
+
|
|
+ ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_PHY_LINK_SETTING_BD_NUM);
|
|
+ if (ret) {
|
|
+ dev_err(&hdev->pdev->dev,
|
|
+ "failed to set phy link ksettings, ret = %d.\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ hdev->hw.mac.autoneg = cmd->base.autoneg;
|
|
+ hdev->hw.mac.speed = cmd->base.speed;
|
|
+ hdev->hw.mac.duplex = cmd->base.duplex;
|
|
+ linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int hclge_update_tp_port_info(struct hclge_dev *hdev)
|
|
+{
|
|
+ struct ethtool_link_ksettings cmd;
|
|
+ int ret;
|
|
+
|
|
+ if (!hnae3_dev_phy_imp_supported(hdev))
|
|
+ return 0;
|
|
+
|
|
+ ret = hclge_get_phy_link_ksettings(&hdev->vport->nic, &cmd);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ hdev->hw.mac.autoneg = cmd.base.autoneg;
|
|
+ hdev->hw.mac.speed = cmd.base.speed;
|
|
+ hdev->hw.mac.duplex = cmd.base.duplex;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int hclge_tp_port_init(struct hclge_dev *hdev)
|
|
+{
|
|
+ struct ethtool_link_ksettings cmd;
|
|
+
|
|
+ if (!hnae3_dev_phy_imp_supported(hdev))
|
|
+ return 0;
|
|
+
|
|
+ cmd.base.autoneg = hdev->hw.mac.autoneg;
|
|
+ cmd.base.speed = hdev->hw.mac.speed;
|
|
+ cmd.base.duplex = hdev->hw.mac.duplex;
|
|
+ linkmode_copy(cmd.link_modes.advertising, hdev->hw.mac.advertising);
|
|
+
|
|
+ return hclge_set_phy_link_ksettings(&hdev->vport->nic, &cmd);
|
|
+}
|
|
+
|
|
static int hclge_update_port_info(struct hclge_dev *hdev)
|
|
{
|
|
struct hclge_mac *mac = &hdev->hw.mac;
|
|
@@ -2911,7 +3046,7 @@ static int hclge_update_port_info(struct hclge_dev *hdev)
|
|
|
|
/* get the port info from SFP cmd if not copper port */
|
|
if (mac->media_type == HNAE3_MEDIA_TYPE_COPPER)
|
|
- return 0;
|
|
+ return hclge_update_tp_port_info(hdev);
|
|
|
|
/* if IMP does not support get SFP/qSFP info, return directly */
|
|
if (!hdev->support_sfp_query)
|
|
@@ -10419,7 +10554,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
|
if (ret)
|
|
goto err_msi_irq_uninit;
|
|
|
|
- if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) {
|
|
+ if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER &&
|
|
+ !hnae3_dev_phy_imp_supported(hdev)) {
|
|
ret = hclge_mac_mdio_config(hdev);
|
|
if (ret)
|
|
goto err_msi_irq_uninit;
|
|
@@ -10796,6 +10932,13 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
|
|
return ret;
|
|
}
|
|
|
|
+ ret = hclge_tp_port_init(hdev);
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "failed to init tp port, ret = %d\n",
|
|
+ ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
ret = hclge_config_tso(hdev, HCLGE_TSO_MSS_MIN, HCLGE_TSO_MSS_MAX);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "Enable tso fail, ret =%d\n", ret);
|
|
@@ -11791,6 +11934,8 @@ struct hnae3_ae_ops hclge_ops = {
|
|
.set_vf_mac = hclge_set_vf_mac,
|
|
.get_module_eeprom = hclge_get_module_eeprom,
|
|
.get_cmdq_stat = hclge_get_cmdq_stat,
|
|
+ .get_phy_link_ksettings = hclge_get_phy_link_ksettings,
|
|
+ .set_phy_link_ksettings = hclge_set_phy_link_ksettings,
|
|
};
|
|
|
|
static struct hnae3_ae_algo ae_algo = {
|
|
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
|
|
index dc69391d2bba..4a43996de6d0 100644
|
|
--- a/include/uapi/linux/ethtool.h
|
|
+++ b/include/uapi/linux/ethtool.h
|
|
@@ -1836,7 +1836,13 @@ struct ethtool_link_settings {
|
|
__u8 eth_tp_mdix_ctrl;
|
|
__s8 link_mode_masks_nwords;
|
|
__u8 transceiver;
|
|
- __u8 reserved1[3];
|
|
+#ifndef __GENKSYMS__
|
|
+ __u8 master_slave_cfg;
|
|
+ __u8 master_slave_state;
|
|
+ __u8 reserved1[1];
|
|
+#else
|
|
+ __u8 reserved1[3];
|
|
+#endif
|
|
__u32 reserved[7];
|
|
__u32 link_mode_masks[0];
|
|
/* layout of link_mode_masks fields:
|
|
--
|
|
2.34.1
|
|
|