Merge branch 'hns3-imp-phys'
Huazhong Tan says: ==================== net: hns3: support imp-controlled PHYs This series adds support for imp-controlled PHYs in the HNS3 ethernet driver. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4849d9beb8
@ -653,6 +653,10 @@ struct hnae3_ae_ops {
|
||||
int (*del_cls_flower)(struct hnae3_handle *handle,
|
||||
struct flow_cls_offload *cls_flower);
|
||||
bool (*cls_flower_active)(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);
|
||||
};
|
||||
|
||||
struct hnae3_dcb_ops {
|
||||
|
@ -365,6 +365,8 @@ static void hns3_dbg_dev_caps(struct hnae3_handle *h)
|
||||
dev_info(&h->pdev->dev, "support PAUSE: %s\n",
|
||||
test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps) ?
|
||||
"yes" : "no");
|
||||
dev_info(&h->pdev->dev, "support imp-controlled PHY: %s\n",
|
||||
test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, caps) ? "yes" : "no");
|
||||
}
|
||||
|
||||
static void hns3_dbg_dev_specs(struct hnae3_handle *h)
|
||||
|
@ -700,6 +700,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;
|
||||
@ -730,7 +731,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);
|
||||
@ -823,6 +827,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)
|
||||
|
@ -385,6 +385,8 @@ static void hclge_parse_capability(struct hclge_dev *hdev,
|
||||
set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps);
|
||||
if (hnae3_get_bit(caps, HCLGE_CAP_PAUSE_B))
|
||||
set_bit(HNAE3_DEV_SUPPORT_PAUSE_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 __le32 hclge_build_api_caps(void)
|
||||
@ -474,6 +476,8 @@ static int hclge_firmware_compat_config(struct hclge_dev *hdev)
|
||||
|
||||
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);
|
||||
|
||||
return hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
|
@ -127,7 +127,7 @@ enum hclge_opcode_type {
|
||||
HCLGE_OPC_QUERY_MAC_TNL_INT = 0x0310,
|
||||
HCLGE_OPC_MAC_TNL_INT_EN = 0x0311,
|
||||
HCLGE_OPC_CLEAR_MAC_TNL_INT = 0x0312,
|
||||
HCLGE_OPC_SERDES_LOOPBACK = 0x0315,
|
||||
HCLGE_OPC_COMMON_LOOPBACK = 0x0315,
|
||||
HCLGE_OPC_CONFIG_FEC_MODE = 0x031A,
|
||||
|
||||
/* PFC/Pause commands */
|
||||
@ -303,6 +303,10 @@ enum hclge_opcode_type {
|
||||
HCLGE_PPP_CMD1_INT_CMD = 0x2101,
|
||||
HCLGE_MAC_ETHERTYPE_IDX_RD = 0x2105,
|
||||
HCLGE_NCSI_INT_EN = 0x2401,
|
||||
|
||||
/* PHY command */
|
||||
HCLGE_OPC_PHY_LINK_KSETTING = 0x7025,
|
||||
HCLGE_OPC_PHY_REG = 0x7026,
|
||||
};
|
||||
|
||||
#define HCLGE_TQP_REG_OFFSET 0x80000
|
||||
@ -960,9 +964,10 @@ struct hclge_pf_rst_done_cmd {
|
||||
|
||||
#define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0)
|
||||
#define HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B BIT(2)
|
||||
#define HCLGE_CMD_SERDES_DONE_B BIT(0)
|
||||
#define HCLGE_CMD_SERDES_SUCCESS_B BIT(1)
|
||||
struct hclge_serdes_lb_cmd {
|
||||
#define HCLGE_CMD_GE_PHY_INNER_LOOP_B BIT(3)
|
||||
#define HCLGE_CMD_COMMON_LB_DONE_B BIT(0)
|
||||
#define HCLGE_CMD_COMMON_LB_SUCCESS_B BIT(1)
|
||||
struct hclge_common_lb_cmd {
|
||||
u8 mask;
|
||||
u8 enable;
|
||||
u8 result;
|
||||
@ -1098,6 +1103,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];
|
||||
@ -1139,6 +1145,36 @@ struct hclge_dev_specs_1_cmd {
|
||||
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];
|
||||
};
|
||||
|
||||
struct hclge_phy_reg_cmd {
|
||||
__le16 reg_addr;
|
||||
u8 rsv0[2];
|
||||
__le16 reg_val;
|
||||
u8 rsv1[18];
|
||||
};
|
||||
|
||||
int hclge_cmd_init(struct hclge_dev *hdev);
|
||||
static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value)
|
||||
{
|
||||
|
@ -1546,13 +1546,13 @@ static void hclge_dbg_dump_loopback(struct hclge_dev *hdev,
|
||||
{
|
||||
struct phy_device *phydev = hdev->hw.mac.phydev;
|
||||
struct hclge_config_mac_mode_cmd *req_app;
|
||||
struct hclge_serdes_lb_cmd *req_serdes;
|
||||
struct hclge_common_lb_cmd *req_common;
|
||||
struct hclge_desc desc;
|
||||
u8 loopback_en;
|
||||
int ret;
|
||||
|
||||
req_app = (struct hclge_config_mac_mode_cmd *)desc.data;
|
||||
req_serdes = (struct hclge_serdes_lb_cmd *)desc.data;
|
||||
req_common = (struct hclge_common_lb_cmd *)desc.data;
|
||||
|
||||
dev_info(&hdev->pdev->dev, "mac id: %u\n", hdev->hw.mac.mac_id);
|
||||
|
||||
@ -1569,27 +1569,33 @@ static void hclge_dbg_dump_loopback(struct hclge_dev *hdev,
|
||||
dev_info(&hdev->pdev->dev, "app loopback: %s\n",
|
||||
loopback_en ? "on" : "off");
|
||||
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, true);
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_COMMON_LOOPBACK, true);
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"failed to dump serdes loopback status, ret = %d\n",
|
||||
"failed to dump common loopback status, ret = %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
|
||||
loopback_en = req_serdes->enable & HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
|
||||
loopback_en = req_common->enable & HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
|
||||
dev_info(&hdev->pdev->dev, "serdes serial loopback: %s\n",
|
||||
loopback_en ? "on" : "off");
|
||||
|
||||
loopback_en = req_serdes->enable &
|
||||
loopback_en = req_common->enable &
|
||||
HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B;
|
||||
dev_info(&hdev->pdev->dev, "serdes parallel loopback: %s\n",
|
||||
loopback_en ? "on" : "off");
|
||||
|
||||
if (phydev)
|
||||
if (phydev) {
|
||||
dev_info(&hdev->pdev->dev, "phy loopback: %s\n",
|
||||
phydev->loopback_enabled ? "on" : "off");
|
||||
} else if (hnae3_dev_phy_imp_supported(hdev)) {
|
||||
loopback_en = req_common->enable &
|
||||
HCLGE_CMD_GE_PHY_INNER_LOOP_B;
|
||||
dev_info(&hdev->pdev->dev, "phy loopback: %s\n",
|
||||
loopback_en ? "on" : "off");
|
||||
}
|
||||
}
|
||||
|
||||
/* hclge_dbg_dump_mac_tnl_status: print message about mac tnl interrupt
|
||||
|
@ -751,8 +751,9 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset)
|
||||
handle->flags |= HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK;
|
||||
handle->flags |= HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
|
||||
|
||||
if (hdev->hw.mac.phydev && hdev->hw.mac.phydev->drv &&
|
||||
hdev->hw.mac.phydev->drv->set_loopback) {
|
||||
if ((hdev->hw.mac.phydev && hdev->hw.mac.phydev->drv &&
|
||||
hdev->hw.mac.phydev->drv->set_loopback) ||
|
||||
hnae3_dev_phy_imp_supported(hdev)) {
|
||||
count += 1;
|
||||
handle->flags |= HNAE3_SUPPORT_PHY_LOOPBACK;
|
||||
}
|
||||
@ -2994,6 +2995,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;
|
||||
@ -3002,7 +3138,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)
|
||||
@ -7135,19 +7271,19 @@ static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hclge_cfg_serdes_loopback(struct hclge_dev *hdev, bool en,
|
||||
static int hclge_cfg_common_loopback(struct hclge_dev *hdev, bool en,
|
||||
enum hnae3_loop loop_mode)
|
||||
{
|
||||
#define HCLGE_SERDES_RETRY_MS 10
|
||||
#define HCLGE_SERDES_RETRY_NUM 100
|
||||
#define HCLGE_COMMON_LB_RETRY_MS 10
|
||||
#define HCLGE_COMMON_LB_RETRY_NUM 100
|
||||
|
||||
struct hclge_serdes_lb_cmd *req;
|
||||
struct hclge_common_lb_cmd *req;
|
||||
struct hclge_desc desc;
|
||||
int ret, i = 0;
|
||||
u8 loop_mode_b;
|
||||
|
||||
req = (struct hclge_serdes_lb_cmd *)desc.data;
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, false);
|
||||
req = (struct hclge_common_lb_cmd *)desc.data;
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_COMMON_LOOPBACK, false);
|
||||
|
||||
switch (loop_mode) {
|
||||
case HNAE3_LOOP_SERIAL_SERDES:
|
||||
@ -7156,9 +7292,12 @@ static int hclge_cfg_serdes_loopback(struct hclge_dev *hdev, bool en,
|
||||
case HNAE3_LOOP_PARALLEL_SERDES:
|
||||
loop_mode_b = HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B;
|
||||
break;
|
||||
case HNAE3_LOOP_PHY:
|
||||
loop_mode_b = HCLGE_CMD_GE_PHY_INNER_LOOP_B;
|
||||
break;
|
||||
default:
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"unsupported serdes loopback mode %d\n", loop_mode);
|
||||
"unsupported common loopback mode %d\n", loop_mode);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
@ -7172,39 +7311,39 @@ static int hclge_cfg_serdes_loopback(struct hclge_dev *hdev, bool en,
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"serdes loopback set fail, ret = %d\n", ret);
|
||||
"common loopback set fail, ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
do {
|
||||
msleep(HCLGE_SERDES_RETRY_MS);
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK,
|
||||
msleep(HCLGE_COMMON_LB_RETRY_MS);
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_COMMON_LOOPBACK,
|
||||
true);
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"serdes loopback get, ret = %d\n", ret);
|
||||
"common loopback get, ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
} while (++i < HCLGE_SERDES_RETRY_NUM &&
|
||||
!(req->result & HCLGE_CMD_SERDES_DONE_B));
|
||||
} while (++i < HCLGE_COMMON_LB_RETRY_NUM &&
|
||||
!(req->result & HCLGE_CMD_COMMON_LB_DONE_B));
|
||||
|
||||
if (!(req->result & HCLGE_CMD_SERDES_DONE_B)) {
|
||||
dev_err(&hdev->pdev->dev, "serdes loopback set timeout\n");
|
||||
if (!(req->result & HCLGE_CMD_COMMON_LB_DONE_B)) {
|
||||
dev_err(&hdev->pdev->dev, "common loopback set timeout\n");
|
||||
return -EBUSY;
|
||||
} else if (!(req->result & HCLGE_CMD_SERDES_SUCCESS_B)) {
|
||||
dev_err(&hdev->pdev->dev, "serdes loopback set failed in fw\n");
|
||||
} else if (!(req->result & HCLGE_CMD_COMMON_LB_SUCCESS_B)) {
|
||||
dev_err(&hdev->pdev->dev, "common loopback set failed in fw\n");
|
||||
return -EIO;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en,
|
||||
static int hclge_set_common_loopback(struct hclge_dev *hdev, bool en,
|
||||
enum hnae3_loop loop_mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hclge_cfg_serdes_loopback(hdev, en, loop_mode);
|
||||
ret = hclge_cfg_common_loopback(hdev, en, loop_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -7253,8 +7392,12 @@ static int hclge_set_phy_loopback(struct hclge_dev *hdev, bool en)
|
||||
struct phy_device *phydev = hdev->hw.mac.phydev;
|
||||
int ret;
|
||||
|
||||
if (!phydev)
|
||||
if (!phydev) {
|
||||
if (hnae3_dev_phy_imp_supported(hdev))
|
||||
return hclge_set_common_loopback(hdev, en,
|
||||
HNAE3_LOOP_PHY);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
if (en)
|
||||
ret = hclge_enable_phy_loopback(hdev, phydev);
|
||||
@ -7325,7 +7468,7 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
|
||||
break;
|
||||
case HNAE3_LOOP_SERIAL_SERDES:
|
||||
case HNAE3_LOOP_PARALLEL_SERDES:
|
||||
ret = hclge_set_serdes_loopback(hdev, en, loop_mode);
|
||||
ret = hclge_set_common_loopback(hdev, en, loop_mode);
|
||||
break;
|
||||
case HNAE3_LOOP_PHY:
|
||||
ret = hclge_set_phy_loopback(hdev, en);
|
||||
@ -7358,11 +7501,11 @@ static int hclge_set_default_loopback(struct hclge_dev *hdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hclge_cfg_serdes_loopback(hdev, false, HNAE3_LOOP_SERIAL_SERDES);
|
||||
ret = hclge_cfg_common_loopback(hdev, false, HNAE3_LOOP_SERIAL_SERDES);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return hclge_cfg_serdes_loopback(hdev, false,
|
||||
return hclge_cfg_common_loopback(hdev, false,
|
||||
HNAE3_LOOP_PARALLEL_SERDES);
|
||||
}
|
||||
|
||||
@ -8769,6 +8912,29 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclge_mii_ioctl(struct hclge_dev *hdev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
struct mii_ioctl_data *data = if_mii(ifr);
|
||||
|
||||
if (!hnae3_dev_phy_imp_supported(hdev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCGMIIPHY:
|
||||
data->phy_id = hdev->hw.mac.phy_addr;
|
||||
/* this command reads phy id and register at the same time */
|
||||
fallthrough;
|
||||
case SIOCGMIIREG:
|
||||
data->val_out = hclge_read_phy_reg(hdev, data->reg_num);
|
||||
return 0;
|
||||
|
||||
case SIOCSMIIREG:
|
||||
return hclge_write_phy_reg(hdev, data->reg_num, data->val_in);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr,
|
||||
int cmd)
|
||||
{
|
||||
@ -8776,7 +8942,7 @@ static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr,
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
|
||||
if (!hdev->hw.mac.phydev)
|
||||
return -EOPNOTSUPP;
|
||||
return hclge_mii_ioctl(hdev, ifr, cmd);
|
||||
|
||||
return phy_mii_ioctl(hdev->hw.mac.phydev, ifr, cmd);
|
||||
}
|
||||
@ -10023,9 +10189,10 @@ static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg,
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
struct phy_device *phydev = hdev->hw.mac.phydev;
|
||||
u8 media_type = hdev->hw.mac.media_type;
|
||||
|
||||
*auto_neg = phydev ? hclge_get_autoneg(handle) : 0;
|
||||
*auto_neg = (media_type == HNAE3_MEDIA_TYPE_COPPER) ?
|
||||
hclge_get_autoneg(handle) : 0;
|
||||
|
||||
if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) {
|
||||
*rx_en = 0;
|
||||
@ -10071,7 +10238,7 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
|
||||
struct phy_device *phydev = hdev->hw.mac.phydev;
|
||||
u32 fc_autoneg;
|
||||
|
||||
if (phydev) {
|
||||
if (phydev || hnae3_dev_phy_imp_supported(hdev)) {
|
||||
fc_autoneg = hclge_get_autoneg(handle);
|
||||
if (auto_neg != fc_autoneg) {
|
||||
dev_info(&hdev->pdev->dev,
|
||||
@ -10090,7 +10257,7 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
|
||||
|
||||
hclge_record_user_pauseparam(hdev, rx_en, tx_en);
|
||||
|
||||
if (!auto_neg)
|
||||
if (!auto_neg || hnae3_dev_phy_imp_supported(hdev))
|
||||
return hclge_cfg_pauseparam(hdev, rx_en, tx_en);
|
||||
|
||||
if (phydev)
|
||||
@ -10648,7 +10815,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;
|
||||
@ -11041,6 +11209,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);
|
||||
@ -11982,6 +12157,8 @@ static const struct hnae3_ae_ops hclge_ops = {
|
||||
.add_cls_flower = hclge_add_cls_flower,
|
||||
.del_cls_flower = hclge_del_cls_flower,
|
||||
.cls_flower_active = hclge_is_cls_flower_active,
|
||||
.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 = {
|
||||
|
@ -268,3 +268,42 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev)
|
||||
|
||||
phy_stop(phydev);
|
||||
}
|
||||
|
||||
u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr)
|
||||
{
|
||||
struct hclge_phy_reg_cmd *req;
|
||||
struct hclge_desc desc;
|
||||
int ret;
|
||||
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PHY_REG, true);
|
||||
|
||||
req = (struct hclge_phy_reg_cmd *)desc.data;
|
||||
req->reg_addr = cpu_to_le16(reg_addr);
|
||||
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret)
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"failed to read phy reg, ret = %d.\n", ret);
|
||||
|
||||
return le16_to_cpu(req->reg_val);
|
||||
}
|
||||
|
||||
int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val)
|
||||
{
|
||||
struct hclge_phy_reg_cmd *req;
|
||||
struct hclge_desc desc;
|
||||
int ret;
|
||||
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PHY_REG, false);
|
||||
|
||||
req = (struct hclge_phy_reg_cmd *)desc.data;
|
||||
req->reg_addr = cpu_to_le16(reg_addr);
|
||||
req->reg_val = cpu_to_le16(val);
|
||||
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret)
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"failed to write phy reg, ret = %d.\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -9,5 +9,7 @@ int hclge_mac_connect_phy(struct hnae3_handle *handle);
|
||||
void hclge_mac_disconnect_phy(struct hnae3_handle *handle);
|
||||
void hclge_mac_start_phy(struct hclge_dev *hdev);
|
||||
void hclge_mac_stop_phy(struct hclge_dev *hdev);
|
||||
u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr);
|
||||
int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user