Commit 01f2b3da authored by Luo bin's avatar Luo bin Committed by David S. Miller

hinic: add link_ksettings ethtool_ops support

add set_link_ksettings implementation and improve the implementation
of get_link_ksettings
Signed-off-by: default avatarLuo bin <luobin9@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9c8255c8
...@@ -219,6 +219,19 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, ...@@ -219,6 +219,19 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd,
HINIC_MGMT_MSG_SYNC); HINIC_MGMT_MSG_SYNC);
} }
int hinic_hilink_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_hilink_cmd cmd,
void *buf_in, u16 in_size, void *buf_out,
u16 *out_size)
{
struct hinic_pfhwdev *pfhwdev;
pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_HILINK, cmd,
buf_in, in_size, buf_out, out_size,
HINIC_MGMT_MSG_SYNC);
}
/** /**
* init_fw_ctxt- Init Firmware tables before network mgmt and io operations * init_fw_ctxt- Init Firmware tables before network mgmt and io operations
* @hwdev: the NIC HW device * @hwdev: the NIC HW device
......
...@@ -54,6 +54,9 @@ enum hinic_port_cmd { ...@@ -54,6 +54,9 @@ enum hinic_port_cmd {
HINIC_PORT_CMD_SET_RX_MODE = 12, HINIC_PORT_CMD_SET_RX_MODE = 12,
HINIC_PORT_CMD_GET_PAUSE_INFO = 20,
HINIC_PORT_CMD_SET_PAUSE_INFO = 21,
HINIC_PORT_CMD_GET_LINK_STATE = 24, HINIC_PORT_CMD_GET_LINK_STATE = 24,
HINIC_PORT_CMD_SET_LRO = 25, HINIC_PORT_CMD_SET_LRO = 25,
...@@ -116,11 +119,23 @@ enum hinic_port_cmd { ...@@ -116,11 +119,23 @@ enum hinic_port_cmd {
HINIC_PORT_CMD_GET_CAP = 170, HINIC_PORT_CMD_GET_CAP = 170,
HINIC_PORT_CMD_GET_LINK_MODE = 217,
HINIC_PORT_CMD_SET_SPEED = 218,
HINIC_PORT_CMD_SET_AUTONEG = 219,
HINIC_PORT_CMD_SET_LRO_TIMER = 244, HINIC_PORT_CMD_SET_LRO_TIMER = 244,
HINIC_PORT_CMD_SET_VF_MAX_MIN_RATE = 249, HINIC_PORT_CMD_SET_VF_MAX_MIN_RATE = 249,
}; };
/* cmd of mgmt CPU message for HILINK module */
enum hinic_hilink_cmd {
HINIC_HILINK_CMD_GET_LINK_INFO = 0x3,
HINIC_HILINK_CMD_SET_LINK_SETTINGS = 0x8,
};
enum hinic_ucode_cmd { enum hinic_ucode_cmd {
HINIC_UCODE_CMD_MODIFY_QUEUE_CONTEXT = 0, HINIC_UCODE_CMD_MODIFY_QUEUE_CONTEXT = 0,
HINIC_UCODE_CMD_CLEAN_QUEUE_CONTEXT, HINIC_UCODE_CMD_CLEAN_QUEUE_CONTEXT,
...@@ -328,6 +343,10 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, ...@@ -328,6 +343,10 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd,
void *buf_in, u16 in_size, void *buf_out, void *buf_in, u16 in_size, void *buf_out,
u16 *out_size); u16 *out_size);
int hinic_hilink_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_hilink_cmd cmd,
void *buf_in, u16 in_size, void *buf_out,
u16 *out_size);
int hinic_hwdev_ifup(struct hinic_hwdev *hwdev); int hinic_hwdev_ifup(struct hinic_hwdev *hwdev);
void hinic_hwdev_ifdown(struct hinic_hwdev *hwdev); void hinic_hwdev_ifdown(struct hinic_hwdev *hwdev);
......
...@@ -192,7 +192,7 @@ enum hinic_mod_type { ...@@ -192,7 +192,7 @@ enum hinic_mod_type {
HINIC_MOD_COMM = 0, /* HW communication module */ HINIC_MOD_COMM = 0, /* HW communication module */
HINIC_MOD_L2NIC = 1, /* L2NIC module */ HINIC_MOD_L2NIC = 1, /* L2NIC module */
HINIC_MOD_CFGM = 7, /* Configuration module */ HINIC_MOD_CFGM = 7, /* Configuration module */
HINIC_MOD_HILINK = 14, /* Hilink module */
HINIC_MOD_MAX = 15 HINIC_MOD_MAX = 15
}; };
......
...@@ -1072,3 +1072,132 @@ int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver) ...@@ -1072,3 +1072,132 @@ int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver)
return 0; 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;
}
...@@ -79,6 +79,42 @@ enum hinic_speed { ...@@ -79,6 +79,42 @@ enum hinic_speed {
HINIC_SPEED_UNKNOWN = 0xFF, HINIC_SPEED_UNKNOWN = 0xFF,
}; };
enum hinic_link_mode {
HINIC_10GE_BASE_KR = 0,
HINIC_40GE_BASE_KR4 = 1,
HINIC_40GE_BASE_CR4 = 2,
HINIC_100GE_BASE_KR4 = 3,
HINIC_100GE_BASE_CR4 = 4,
HINIC_25GE_BASE_KR_S = 5,
HINIC_25GE_BASE_CR_S = 6,
HINIC_25GE_BASE_KR = 7,
HINIC_25GE_BASE_CR = 8,
HINIC_GE_BASE_KX = 9,
HINIC_LINK_MODE_NUMBERS,
HINIC_SUPPORTED_UNKNOWN = 0xFFFF,
};
enum hinic_port_type {
HINIC_PORT_TP, /* BASET */
HINIC_PORT_AUI,
HINIC_PORT_MII,
HINIC_PORT_FIBRE, /* OPTICAL */
HINIC_PORT_BNC,
HINIC_PORT_ELEC,
HINIC_PORT_COPPER, /* PORT_DA */
HINIC_PORT_AOC,
HINIC_PORT_BACKPLANE,
HINIC_PORT_NONE = 0xEF,
HINIC_PORT_OTHER = 0xFF,
};
enum hinic_valid_link_settings {
HILINK_LINK_SET_SPEED = 0x1,
HILINK_LINK_SET_AUTONEG = 0x2,
HILINK_LINK_SET_FEC = 0x4,
};
enum hinic_tso_state { enum hinic_tso_state {
HINIC_TSO_DISABLE = 0, HINIC_TSO_DISABLE = 0,
HINIC_TSO_ENABLE = 1, HINIC_TSO_ENABLE = 1,
...@@ -179,6 +215,50 @@ struct hinic_port_cap { ...@@ -179,6 +215,50 @@ struct hinic_port_cap {
u8 rsvd2[3]; u8 rsvd2[3];
}; };
struct hinic_link_mode_cmd {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 rsvd1;
u16 supported; /* 0xFFFF represents invalid value */
u16 advertised;
};
struct hinic_speed_cmd {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 speed;
};
struct hinic_set_autoneg_cmd {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 enable; /* 1: enable , 0: disable */
};
struct hinic_link_ksettings_info {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 rsvd1;
u32 valid_bitmap;
u32 speed; /* enum nic_speed_level */
u8 autoneg; /* 0 - off; 1 - on */
u8 fec; /* 0 - RSFEC; 1 - BASEFEC; 2 - NOFEC */
u8 rsvd2[18]; /* reserved for duplex, port, etc. */
};
struct hinic_tso_config { struct hinic_tso_config {
u8 status; u8 status;
u8 version; u8 version;
...@@ -549,6 +629,18 @@ struct hinic_spoofchk_set { ...@@ -549,6 +629,18 @@ struct hinic_spoofchk_set {
u16 func_id; u16 func_id;
}; };
struct hinic_pause_config {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 rsvd1;
u32 auto_neg;
u32 rx_pause;
u32 tx_pause;
};
int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr, int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
u16 vlan_id); u16 vlan_id);
...@@ -628,4 +720,20 @@ int hinic_set_rx_vlan_offload(struct hinic_dev *nic_dev, u8 en); ...@@ -628,4 +720,20 @@ int hinic_set_rx_vlan_offload(struct hinic_dev *nic_dev, u8 en);
int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver); int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver);
int hinic_set_link_settings(struct hinic_hwdev *hwdev,
struct hinic_link_ksettings_info *info);
int hinic_get_link_mode(struct hinic_hwdev *hwdev,
struct hinic_link_mode_cmd *link_mode);
int hinic_set_autoneg(struct hinic_hwdev *hwdev, bool enable);
int hinic_set_speed(struct hinic_hwdev *hwdev, enum nic_speed_level speed);
int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev,
struct hinic_pause_config *pause_info);
int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
struct hinic_pause_config *pause_info);
#endif #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