[PATCH topic-hns-5.1 3/3] {topost} net: hns3: add support for FEC encoding control

From: Jian Shen
Date: Fri Apr 26 2019 - 05:43:23 EST


This patch adds support for FEC encoding control, user can change
FEC mode by command ethtool --set-fec, and get FEC mode by command
ethtool --show-fec. The fec capability is changed follow the port
speed. If autoneg on, the user configure fec mode will be overwritten
by autoneg result.

Signed-off-by: Jian Shen <shenjian15@xxxxxxxxxx>
---
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 13 ++++
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 16 +++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 78 ++--------------------
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 +
4 files changed, 38 insertions(+), 71 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 010ba8a..6e67621 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -126,6 +126,12 @@ enum hnae3_module_type {

};

+enum hnae3_fec_mode {
+ HNAE3_FEC_AUTO = 0,
+ HNAE3_FEC_BASER,
+ HNAE3_FEC_RS,
+};
+
enum hnae3_reset_notify_type {
HNAE3_UP_CLIENT,
HNAE3_DOWN_CLIENT,
@@ -238,6 +244,10 @@ struct hnae3_ae_dev {
* Get media type of MAC
* check_port_speed()
* Check target speed whether is supported
+ * get_fec()
+ * Get fec ability and fec mode
+ * set_fec()
+ * Set fec
* adjust_link()
* Adjust link status
* set_loopback()
@@ -356,6 +366,9 @@ struct hnae3_ae_ops {
void (*get_media_type)(struct hnae3_handle *handle, u8 *media_type,
u8 *module_type);
int (*check_port_speed)(struct hnae3_handle *handle, u32 speed);
+ void (*get_fec)(struct hnae3_handle *handle, u8 *fec_ability,
+ u8 *fec_mode);
+ int (*set_fec)(struct hnae3_handle *handle, u32 fec_mode);
void (*adjust_link)(struct hnae3_handle *handle, int speed, int duplex);
int (*set_loopback)(struct hnae3_handle *handle,
enum hnae3_loop loop_mode, bool en);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 5c82e11..67d1d97 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -115,6 +115,7 @@ enum hclge_opcode_type {
HCLGE_OPC_MAC_TNL_INT_EN = 0x0311,
HCLGE_OPC_CLEAR_MAC_TNL_INT = 0x0312,
HCLGE_OPC_SERDES_LOOPBACK = 0x0315,
+ HCLGE_OPC_CONFIG_FEC_MODE = 0x031A,

/* PFC/Pause commands */
HCLGE_OPC_CFG_MAC_PAUSE_EN = 0x0701,
@@ -613,6 +614,21 @@ struct hclge_sfp_info_cmd {
u8 rsv[8];
};

+#define HCLGE_MAC_CFG_FEC_AUTO_EN_B 0
+#define HCLGE_MAC_CFG_FEC_MODE_S 1
+#define HCLGE_MAC_CFG_FEC_MODE_M GENMASK(3, 1)
+#define HCLGE_MAC_CFG_FEC_SET_DEF_B 0
+#define HCLGE_MAC_CFG_FEC_CLR_DEF_B 1
+
+#define HCLGE_MAC_FEC_OFF 0
+#define HCLGE_MAC_FEC_BASER 1
+#define HCLGE_MAC_FEC_RS 2
+struct hclge_config_fec_cmd {
+ u8 fec_mode;
+ u8 default_config;
+ u8 rsv[22];
+};
+
#define HCLGE_MAC_UPLINK_PORT 0x100

struct hclge_config_max_frm_size_cmd {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index ea3ac4c..58c0621 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -843,48 +843,6 @@ static int hclge_parse_speed(int speed_cmd, int *speed)
return 0;
}

-static int hclge_check_port_speed(struct hnae3_handle *handle, u32 speed)
-{
- struct hclge_vport *vport = hclge_get_vport(handle);
- struct hclge_dev *hdev = vport->back;
- u32 speed_ability = hdev->hw.mac.speed_ability;
- u32 speed_bit = 0;
-
- switch (speed) {
- case HCLGE_MAC_SPEED_10M:
- speed_bit = HCLGE_SUPPORT_10M_BIT;
- break;
- case HCLGE_MAC_SPEED_100M:
- speed_bit = HCLGE_SUPPORT_100M_BIT;
- break;
- case HCLGE_MAC_SPEED_1G:
- speed_bit = HCLGE_SUPPORT_1G_BIT;
- break;
- case HCLGE_MAC_SPEED_10G:
- speed_bit = HCLGE_SUPPORT_10G_BIT;
- break;
- case HCLGE_MAC_SPEED_25G:
- speed_bit = HCLGE_SUPPORT_25G_BIT;
- break;
- case HCLGE_MAC_SPEED_40G:
- speed_bit = HCLGE_SUPPORT_40G_BIT;
- break;
- case HCLGE_MAC_SPEED_50G:
- speed_bit = HCLGE_SUPPORT_50G_BIT;
- break;
- case HCLGE_MAC_SPEED_100G:
- speed_bit = HCLGE_SUPPORT_100G_BIT;
- break;
- default:
- return -EINVAL;
- }
-
- if (speed_bit & speed_ability)
- return 0;
-
- return -EINVAL;
-}
-
static void hclge_convert_setting_sr(struct hclge_mac *mac, u8 speed_ability)
{
if (speed_ability & HCLGE_SUPPORT_10G_BIT)
@@ -2232,16 +2190,6 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable)
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;

- if (!hdev->hw.mac.support_autoneg) {
- if (enable) {
- dev_err(&hdev->pdev->dev,
- "autoneg is not supported by current port\n");
- return -EOPNOTSUPP;
- } else {
- return 0;
- }
- }
-
return hclge_set_autoneg_en(hdev, enable);
}

@@ -2257,18 +2205,6 @@ static int hclge_get_autoneg(struct hnae3_handle *handle)
return hdev->hw.mac.autoneg;
}

-static int hclge_restart_autoneg(struct hnae3_handle *handle)
-{
- struct hclge_vport *vport = hclge_get_vport(handle);
- struct hclge_dev *hdev = vport->back;
- int ret;
-
- ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
- if (ret)
- return ret;
- return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
-}
-
static int hclge_mac_init(struct hclge_dev *hdev)
{
struct hclge_mac *mac = &hdev->hw.mac;
@@ -2465,6 +2401,8 @@ static int hclge_get_sfp_info(struct hclge_dev *hdev, struct hclge_mac *mac)
mac->speed_ability = le32_to_cpu(resp->speed_ability);
mac->autoneg = resp->autoneg;
mac->support_autoneg = resp->autoneg_ability;
+ mac->fec_mode = resp->active_fec ? BIT(resp->active_fec) : 0;
+
} else {
mac->speed_type = QUERY_SFP_SPEED;
}
@@ -8009,13 +7947,13 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
if (!fc_autoneg)
return hclge_cfg_pauseparam(hdev, rx_en, tx_en);

- if (phydev)
- return phy_start_aneg(phydev);
-
- if (hdev->pdev->revision == 0x20)
+ /* Only support flow control negotiation for netdev with
+ * phy attached for now.
+ */
+ if (!phydev)
return -EOPNOTSUPP;

- return hclge_restart_autoneg(handle);
+ return phy_start_aneg(phydev);
}

static void hclge_get_ksettings_an_result(struct hnae3_handle *handle,
@@ -9140,7 +9078,6 @@ static int hclge_gro_en(struct hnae3_handle *handle, bool enable)
.get_ksettings_an_result = hclge_get_ksettings_an_result,
.cfg_mac_speed_dup_h = hclge_cfg_mac_speed_dup_h,
.get_media_type = hclge_get_media_type,
- .check_port_speed = hclge_check_port_speed,
.get_rss_key_size = hclge_get_rss_key_size,
.get_rss_indir_size = hclge_get_rss_indir_size,
.get_rss = hclge_get_rss,
@@ -9157,7 +9094,6 @@ static int hclge_gro_en(struct hnae3_handle *handle, bool enable)
.rm_mc_addr = hclge_rm_mc_addr,
.set_autoneg = hclge_set_autoneg,
.get_autoneg = hclge_get_autoneg,
- .restart_autoneg = hclge_restart_autoneg,
.get_pauseparam = hclge_get_pauseparam,
.set_pauseparam = hclge_set_pauseparam,
.set_mtu = hclge_set_mtu,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 50d6ad0..2928732 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -255,6 +255,8 @@ struct hclge_mac {
u32 speed;
u32 speed_ability; /* speed ability supported by current media */
u32 module_type; /* sub media type, e.g. kr/cr/sr/lr */
+ u32 fec_mode;
+ u32 fec_ability;
int link; /* store the link status of mac & phy (if phy exit) */
struct phy_device *phydev;
struct mii_bus *mdio_bus;
--
1.9.1