mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
net: hns3: add support to query and set lane number by ethtool
When serdes lane support setting 25Gb/s or 50Gb/s speed and user wants to set port speed as 50Gb/s, it can be setted as one 50Gb/s serdes lane or two 25Gb/s serdes lanes. So, this patch adds support to query and set lane number by ethtool to satisfy this scenario. Signed-off-by: Hao Chen <chenhao418@huawei.com> Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2cb343b9d3
commit
0f032f93c4
10 changed files with 50 additions and 23 deletions
|
@ -98,6 +98,7 @@ enum HNAE3_DEV_CAP_BITS {
|
|||
HNAE3_DEV_SUPPORT_MC_MAC_MNG_B,
|
||||
HNAE3_DEV_SUPPORT_CQ_B,
|
||||
HNAE3_DEV_SUPPORT_FEC_STATS_B,
|
||||
HNAE3_DEV_SUPPORT_LANE_NUM_B,
|
||||
};
|
||||
|
||||
#define hnae3_ae_dev_fd_supported(ae_dev) \
|
||||
|
@ -163,6 +164,9 @@ enum HNAE3_DEV_CAP_BITS {
|
|||
#define hnae3_ae_dev_fec_stats_supported(ae_dev) \
|
||||
test_bit(HNAE3_DEV_SUPPORT_FEC_STATS_B, (ae_dev)->caps)
|
||||
|
||||
#define hnae3_ae_dev_lane_num_supported(ae_dev) \
|
||||
test_bit(HNAE3_DEV_SUPPORT_LANE_NUM_B, (ae_dev)->caps)
|
||||
|
||||
enum HNAE3_PF_CAP_BITS {
|
||||
HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0,
|
||||
};
|
||||
|
@ -572,10 +576,11 @@ struct hnae3_ae_ops {
|
|||
void (*client_stop)(struct hnae3_handle *handle);
|
||||
int (*get_status)(struct hnae3_handle *handle);
|
||||
void (*get_ksettings_an_result)(struct hnae3_handle *handle,
|
||||
u8 *auto_neg, u32 *speed, u8 *duplex);
|
||||
u8 *auto_neg, u32 *speed, u8 *duplex,
|
||||
u32 *lane_num);
|
||||
|
||||
int (*cfg_mac_speed_dup_h)(struct hnae3_handle *handle, int speed,
|
||||
u8 duplex);
|
||||
u8 duplex, u8 lane_num);
|
||||
|
||||
void (*get_media_type)(struct hnae3_handle *handle, u8 *media_type,
|
||||
u8 *module_type);
|
||||
|
|
|
@ -154,6 +154,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = {
|
|||
{HCLGE_COMM_CAP_GRO_B, HNAE3_DEV_SUPPORT_GRO_B},
|
||||
{HCLGE_COMM_CAP_FD_B, HNAE3_DEV_SUPPORT_FD_B},
|
||||
{HCLGE_COMM_CAP_FEC_STATS_B, HNAE3_DEV_SUPPORT_FEC_STATS_B},
|
||||
{HCLGE_COMM_CAP_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B},
|
||||
};
|
||||
|
||||
static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
|
||||
|
|
|
@ -344,6 +344,7 @@ enum HCLGE_COMM_CAP_BITS {
|
|||
HCLGE_COMM_CAP_GRO_B = 20,
|
||||
HCLGE_COMM_CAP_FD_B = 21,
|
||||
HCLGE_COMM_CAP_FEC_STATS_B = 25,
|
||||
HCLGE_COMM_CAP_LANE_NUM_B = 27,
|
||||
};
|
||||
|
||||
enum HCLGE_COMM_API_CAP_BITS {
|
||||
|
|
|
@ -405,6 +405,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = {
|
|||
}, {
|
||||
.name = "support FEC statistics",
|
||||
.cap_bit = HNAE3_DEV_SUPPORT_FEC_STATS_B,
|
||||
}, {
|
||||
.name = "support lane num",
|
||||
.cap_bit = HNAE3_DEV_SUPPORT_LANE_NUM_B,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -712,7 +712,8 @@ static void hns3_get_ksettings(struct hnae3_handle *h,
|
|||
ops->get_ksettings_an_result(h,
|
||||
&cmd->base.autoneg,
|
||||
&cmd->base.speed,
|
||||
&cmd->base.duplex);
|
||||
&cmd->base.duplex,
|
||||
&cmd->lanes);
|
||||
|
||||
/* 2.get link mode */
|
||||
if (ops->get_link_mode)
|
||||
|
@ -794,6 +795,7 @@ static int hns3_check_ksettings_param(const struct net_device *netdev,
|
|||
const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
|
||||
u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN;
|
||||
u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN;
|
||||
u32 lane_num;
|
||||
u8 autoneg;
|
||||
u32 speed;
|
||||
u8 duplex;
|
||||
|
@ -806,9 +808,9 @@ static int hns3_check_ksettings_param(const struct net_device *netdev,
|
|||
return 0;
|
||||
|
||||
if (ops->get_ksettings_an_result) {
|
||||
ops->get_ksettings_an_result(handle, &autoneg, &speed, &duplex);
|
||||
ops->get_ksettings_an_result(handle, &autoneg, &speed, &duplex, &lane_num);
|
||||
if (cmd->base.autoneg == autoneg && cmd->base.speed == speed &&
|
||||
cmd->base.duplex == duplex)
|
||||
cmd->base.duplex == duplex && cmd->lanes == lane_num)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -845,10 +847,14 @@ static int hns3_set_link_ksettings(struct net_device *netdev,
|
|||
if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF)
|
||||
return -EINVAL;
|
||||
|
||||
if (cmd->lanes && !hnae3_ae_dev_lane_num_supported(ae_dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
netif_dbg(handle, drv, netdev,
|
||||
"set link(%s): autoneg=%u, speed=%u, duplex=%u\n",
|
||||
"set link(%s): autoneg=%u, speed=%u, duplex=%u, lanes=%u\n",
|
||||
netdev->phydev ? "phy" : "mac",
|
||||
cmd->base.autoneg, cmd->base.speed, cmd->base.duplex);
|
||||
cmd->base.autoneg, cmd->base.speed, cmd->base.duplex,
|
||||
cmd->lanes);
|
||||
|
||||
/* Only support ksettings_set for netdev with phy attached for now */
|
||||
if (netdev->phydev) {
|
||||
|
@ -886,7 +892,7 @@ static int hns3_set_link_ksettings(struct net_device *netdev,
|
|||
|
||||
if (ops->cfg_mac_speed_dup_h)
|
||||
ret = ops->cfg_mac_speed_dup_h(handle, cmd->base.speed,
|
||||
cmd->base.duplex);
|
||||
cmd->base.duplex, (u8)(cmd->lanes));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2067,6 +2073,7 @@ static const struct ethtool_ops hns3vf_ethtool_ops = {
|
|||
static const struct ethtool_ops hns3_ethtool_ops = {
|
||||
.supported_coalesce_params = HNS3_ETHTOOL_COALESCE,
|
||||
.supported_ring_params = HNS3_ETHTOOL_RING,
|
||||
.cap_link_lanes_supported = true,
|
||||
.self_test = hns3_self_test,
|
||||
.get_drvinfo = hns3_get_drvinfo,
|
||||
.get_link = hns3_get_link,
|
||||
|
|
|
@ -321,7 +321,9 @@ struct hclge_config_mac_speed_dup_cmd {
|
|||
|
||||
#define HCLGE_CFG_MAC_SPEED_CHANGE_EN_B 0
|
||||
u8 mac_change_fec_en;
|
||||
u8 rsv[22];
|
||||
u8 rsv[4];
|
||||
u8 lane_num;
|
||||
u8 rsv1[17];
|
||||
};
|
||||
|
||||
#define HCLGE_TQP_ENABLE_B 0
|
||||
|
@ -348,7 +350,8 @@ struct hclge_sfp_info_cmd {
|
|||
__le32 speed_ability; /* speed ability for current media */
|
||||
__le32 module_type;
|
||||
u8 fec_ability;
|
||||
u8 rsv[7];
|
||||
u8 lane_num;
|
||||
u8 rsv[6];
|
||||
};
|
||||
|
||||
#define HCLGE_MAC_CFG_FEC_AUTO_EN_B 0
|
||||
|
|
|
@ -2615,7 +2615,7 @@ static int hclge_convert_to_fw_speed(u32 speed_drv, u32 *speed_fw)
|
|||
}
|
||||
|
||||
static int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed,
|
||||
u8 duplex)
|
||||
u8 duplex, u8 lane_num)
|
||||
{
|
||||
struct hclge_config_mac_speed_dup_cmd *req;
|
||||
struct hclge_desc desc;
|
||||
|
@ -2639,6 +2639,7 @@ static int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed,
|
|||
speed_fw);
|
||||
hnae3_set_bit(req->mac_change_fec_en, HCLGE_CFG_MAC_SPEED_CHANGE_EN_B,
|
||||
1);
|
||||
req->lane_num = lane_num;
|
||||
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret) {
|
||||
|
@ -2650,33 +2651,35 @@ static int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex)
|
||||
int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex, u8 lane_num)
|
||||
{
|
||||
struct hclge_mac *mac = &hdev->hw.mac;
|
||||
int ret;
|
||||
|
||||
duplex = hclge_check_speed_dup(duplex, speed);
|
||||
if (!mac->support_autoneg && mac->speed == speed &&
|
||||
mac->duplex == duplex)
|
||||
mac->duplex == duplex && (mac->lane_num == lane_num || lane_num == 0))
|
||||
return 0;
|
||||
|
||||
ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex);
|
||||
ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex, lane_num);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdev->hw.mac.speed = speed;
|
||||
hdev->hw.mac.duplex = duplex;
|
||||
if (!lane_num)
|
||||
hdev->hw.mac.lane_num = lane_num;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed,
|
||||
u8 duplex)
|
||||
u8 duplex, u8 lane_num)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
|
||||
return hclge_cfg_mac_speed_dup(hdev, speed, duplex);
|
||||
return hclge_cfg_mac_speed_dup(hdev, speed, duplex, lane_num);
|
||||
}
|
||||
|
||||
static int hclge_set_autoneg_en(struct hclge_dev *hdev, bool enable)
|
||||
|
@ -2976,7 +2979,7 @@ static int hclge_mac_init(struct hclge_dev *hdev)
|
|||
hdev->support_sfp_query = true;
|
||||
hdev->hw.mac.duplex = HCLGE_MAC_FULL;
|
||||
ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed,
|
||||
hdev->hw.mac.duplex);
|
||||
hdev->hw.mac.duplex, hdev->hw.mac.lane_num);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -3301,6 +3304,7 @@ static int hclge_get_sfp_info(struct hclge_dev *hdev, struct hclge_mac *mac)
|
|||
mac->autoneg = resp->autoneg;
|
||||
mac->support_autoneg = resp->autoneg_ability;
|
||||
mac->speed_type = QUERY_ACTIVE_SPEED;
|
||||
mac->lane_num = resp->lane_num;
|
||||
if (!resp->active_fec)
|
||||
mac->fec_mode = 0;
|
||||
else
|
||||
|
@ -3485,13 +3489,13 @@ static int hclge_update_port_info(struct hclge_dev *hdev)
|
|||
return 0;
|
||||
}
|
||||
return hclge_cfg_mac_speed_dup(hdev, mac->speed,
|
||||
HCLGE_MAC_FULL);
|
||||
HCLGE_MAC_FULL, mac->lane_num);
|
||||
} else {
|
||||
if (speed == HCLGE_MAC_SPEED_UNKNOWN)
|
||||
return 0; /* do nothing if no SFP */
|
||||
|
||||
/* must config full duplex for SFP */
|
||||
return hclge_cfg_mac_speed_dup(hdev, speed, HCLGE_MAC_FULL);
|
||||
return hclge_cfg_mac_speed_dup(hdev, speed, HCLGE_MAC_FULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10985,7 +10989,7 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
|
|||
}
|
||||
|
||||
static void hclge_get_ksettings_an_result(struct hnae3_handle *handle,
|
||||
u8 *auto_neg, u32 *speed, u8 *duplex)
|
||||
u8 *auto_neg, u32 *speed, u8 *duplex, u32 *lane_num)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
|
@ -10996,6 +11000,8 @@ static void hclge_get_ksettings_an_result(struct hnae3_handle *handle,
|
|||
*duplex = hdev->hw.mac.duplex;
|
||||
if (auto_neg)
|
||||
*auto_neg = hdev->hw.mac.autoneg;
|
||||
if (lane_num)
|
||||
*lane_num = hdev->hw.mac.lane_num;
|
||||
}
|
||||
|
||||
static void hclge_get_media_type(struct hnae3_handle *handle, u8 *media_type,
|
||||
|
|
|
@ -259,6 +259,7 @@ struct hclge_mac {
|
|||
u8 duplex;
|
||||
u8 support_autoneg;
|
||||
u8 speed_type; /* 0: sfp speed, 1: active speed */
|
||||
u8 lane_num;
|
||||
u32 speed;
|
||||
u32 max_speed;
|
||||
u32 speed_ability; /* speed ability supported by current media */
|
||||
|
@ -1096,7 +1097,7 @@ static inline int hclge_get_queue_id(struct hnae3_queue *queue)
|
|||
}
|
||||
|
||||
int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport);
|
||||
int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex);
|
||||
int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex, u8 lane_num);
|
||||
int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
|
||||
u16 vlan_id, bool is_kill);
|
||||
int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable);
|
||||
|
|
|
@ -187,7 +187,7 @@ static void hclge_mac_adjust_link(struct net_device *netdev)
|
|||
speed = netdev->phydev->speed;
|
||||
duplex = netdev->phydev->duplex;
|
||||
|
||||
ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
|
||||
ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex, 0);
|
||||
if (ret)
|
||||
netdev_err(netdev, "failed to adjust link.\n");
|
||||
|
||||
|
|
|
@ -3177,7 +3177,7 @@ static int hclgevf_get_status(struct hnae3_handle *handle)
|
|||
|
||||
static void hclgevf_get_ksettings_an_result(struct hnae3_handle *handle,
|
||||
u8 *auto_neg, u32 *speed,
|
||||
u8 *duplex)
|
||||
u8 *duplex, u32 *lane_num)
|
||||
{
|
||||
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue