diff options
author | Luo bin <luobin9@huawei.com> | 2020-05-11 05:58:57 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-05-11 13:19:35 -0700 |
commit | 01f2b3dac8c4bebeb0ec15c4b7b59993766493cc (patch) | |
tree | 5a11f320670bec38bf8a2fa284388e376f061bee /drivers/net/ethernet/huawei/hinic/hinic_port.c | |
parent | 9c8255c888bac9221739c822132b405d4196bdd8 (diff) | |
download | linux-01f2b3dac8c4bebeb0ec15c4b7b59993766493cc.tar.gz |
hinic: add link_ksettings ethtool_ops support
add set_link_ksettings implementation and improve the implementation
of get_link_ksettings
Signed-off-by: Luo bin <luobin9@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/huawei/hinic/hinic_port.c')
-rw-r--r-- | drivers/net/ethernet/huawei/hinic/hinic_port.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c index 714d8279c591..2edb6127f9fb 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_port.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c @@ -1072,3 +1072,132 @@ int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver) return 0; } + +int hinic_get_link_mode(struct hinic_hwdev *hwdev, + struct hinic_link_mode_cmd *link_mode) +{ + u16 out_size; + int err; + + if (!hwdev || !link_mode) + return -EINVAL; + + out_size = sizeof(*link_mode); + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_MODE, + link_mode, sizeof(*link_mode), + link_mode, &out_size); + if (err || !out_size || link_mode->status) { + dev_err(&hwdev->hwif->pdev->dev, + "Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x\n", + err, link_mode->status, out_size); + return -EIO; + } + + return 0; +} + +int hinic_set_autoneg(struct hinic_hwdev *hwdev, bool enable) +{ + struct hinic_set_autoneg_cmd autoneg = {0}; + u16 out_size = sizeof(autoneg); + int err; + + if (!hwdev) + return -EINVAL; + + autoneg.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif); + autoneg.enable = enable; + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_AUTONEG, + &autoneg, sizeof(autoneg), + &autoneg, &out_size); + if (err || !out_size || autoneg.status) { + dev_err(&hwdev->hwif->pdev->dev, "Failed to %s autoneg, err: %d, status: 0x%x, out size: 0x%x\n", + enable ? "enable" : "disable", err, autoneg.status, + out_size); + return -EIO; + } + + return 0; +} + +int hinic_set_speed(struct hinic_hwdev *hwdev, enum nic_speed_level speed) +{ + struct hinic_speed_cmd speed_info = {0}; + u16 out_size = sizeof(speed_info); + int err; + + if (!hwdev) + return -EINVAL; + + speed_info.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif); + speed_info.speed = speed; + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_SPEED, + &speed_info, sizeof(speed_info), + &speed_info, &out_size); + if (err || !out_size || speed_info.status) { + dev_err(&hwdev->hwif->pdev->dev, + "Failed to set speed, err: %d, status: 0x%x, out size: 0x%x\n", + err, speed_info.status, out_size); + return -EIO; + } + + return 0; +} + +int hinic_set_link_settings(struct hinic_hwdev *hwdev, + struct hinic_link_ksettings_info *info) +{ + u16 out_size = sizeof(*info); + int err; + + err = hinic_hilink_msg_cmd(hwdev, HINIC_HILINK_CMD_SET_LINK_SETTINGS, + info, sizeof(*info), info, &out_size); + if ((info->status != HINIC_MGMT_CMD_UNSUPPORTED && + info->status) || err || !out_size) { + dev_err(&hwdev->hwif->pdev->dev, + "Failed to set link settings, err: %d, status: 0x%x, out size: 0x%x\n", + err, info->status, out_size); + return -EFAULT; + } + + return info->status; +} + +int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev, + struct hinic_pause_config *pause_info) +{ + u16 out_size = sizeof(*pause_info); + int err; + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO, + pause_info, sizeof(*pause_info), + pause_info, &out_size); + if (err || !out_size || pause_info->status) { + dev_err(&hwdev->hwif->pdev->dev, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x\n", + err, pause_info->status, out_size); + return -EIO; + } + + return 0; +} + +int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev, + struct hinic_pause_config *pause_info) +{ + u16 out_size = sizeof(*pause_info); + int err; + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO, + pause_info, sizeof(*pause_info), + pause_info, &out_size); + if (err || !out_size || pause_info->status) { + dev_err(&hwdev->hwif->pdev->dev, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x\n", + err, pause_info->status, out_size); + return -EIO; + } + + return 0; +} |