Commit 4849d9be authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 5ab6f96a b47cfe1f
......@@ -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
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