From: Valentine Fatiev <valentinef@nvidia.com>
Subject: [PATCH] BACKPORT:
 drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c

Change-Id: I9da222c3aa56c9de370a7a20bdd85a4140be7dc7
---
 .../mellanox/mlx5/core/ipoib/ethtool.c        | 100 +++++++++++++++++-
 1 file changed, 95 insertions(+), 5 deletions(-)

--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
@@ -40,7 +40,7 @@ static void mlx5i_get_drvinfo(struct net
 	struct mlx5e_priv *priv = mlx5i_epriv(dev);
 
 	mlx5e_ethtool_get_drvinfo(priv, drvinfo);
-	strscpy(drvinfo->driver, KBUILD_MODNAME "[ib_ipoib]",
+        strscpy(drvinfo->driver, KBUILD_MODNAME "[ib_ipoib]",
 		sizeof(drvinfo->driver));
 }
 
@@ -68,9 +68,13 @@ static void mlx5i_get_ethtool_stats(stru
 }
 
 static int mlx5i_set_ringparam(struct net_device *dev,
+#ifdef HAVE_GET_RINGPARAM_GET_4_PARAMS
 			       struct ethtool_ringparam *param,
 			       struct kernel_ethtool_ringparam *kernel_param,
 			       struct netlink_ext_ack *extack)
+#else
+			       struct ethtool_ringparam *param)
+#endif
 {
 	struct mlx5e_priv *priv = mlx5i_epriv(dev);
 
@@ -78,13 +82,24 @@ static int mlx5i_set_ringparam(struct ne
 }
 
 static void mlx5i_get_ringparam(struct net_device *dev,
+#ifdef HAVE_GET_RINGPARAM_GET_4_PARAMS
 				struct ethtool_ringparam *param,
+#ifdef HAVE_STRUCT_KERNEL_ETHTOOL_RINGPARAM
 				struct kernel_ethtool_ringparam *kernel_param,
+#else
+				struct ethtool_ringparam *param,
+#endif
 				struct netlink_ext_ack *extack)
+#else
+				struct ethtool_ringparam *param)
+#endif
 {
 	struct mlx5e_priv *priv = mlx5i_epriv(dev);
-
+#if defined(HAVE_STRUCT_KERNEL_ETHTOOL_RINGPARAM) && defined(HAVE_GET_RINGPARAM_GET_4_PARAMS)
 	mlx5e_ethtool_get_ringparam(priv, param, kernel_param);
+#else
+	mlx5e_ethtool_get_ringparam(priv, param);
+#endif
 }
 
 static int mlx5i_set_channels(struct net_device *dev,
@@ -116,23 +131,41 @@ static void mlx5i_get_channels(struct ne
 }
 
 static int mlx5i_set_coalesce(struct net_device *netdev,
+#ifdef HAVE_NDO_GET_COALESCE_GET_4_PARAMS
 			      struct ethtool_coalesce *coal,
 			      struct kernel_ethtool_coalesce *kernel_coal,
 			      struct netlink_ext_ack *extack)
+#else
+ 			      struct ethtool_coalesce *coal)
+#endif
 {
 	struct mlx5e_priv *priv = mlx5i_epriv(netdev);
 
-	return mlx5e_ethtool_set_coalesce(priv, coal, kernel_coal, extack);
+	return mlx5e_ethtool_set_coalesce(priv,
+#ifdef HAVE_NDO_GET_COALESCE_GET_4_PARAMS
+					  coal, kernel_coal, extack);
+#else
+					  coal);
+#endif
 }
 
 static int mlx5i_get_coalesce(struct net_device *netdev,
+#ifdef HAVE_NDO_GET_COALESCE_GET_4_PARAMS
 			      struct ethtool_coalesce *coal,
 			      struct kernel_ethtool_coalesce *kernel_coal,
 			      struct netlink_ext_ack *extack)
+#else
+ 			      struct ethtool_coalesce *coal)
+#endif
 {
 	struct mlx5e_priv *priv = mlx5i_epriv(netdev);
 
-	return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal);
+	return mlx5e_ethtool_get_coalesce(priv,
+#ifdef HAVE_NDO_GET_COALESCE_GET_4_PARAMS
+					  coal, kernel_coal);
+#else
+					  coal);
+#endif
 }
 
 static int mlx5i_get_ts_info(struct net_device *netdev,
@@ -233,6 +266,53 @@ static int mlx5i_get_link_ksettings(stru
 	return 0;
 }
 
+#ifdef HAVE_ETHTOOL_GET_SET_SETTINGS
+static int mlx5i_get_port_settings(struct net_device *netdev,
+		u16 *ib_link_width_oper, u16 *ib_proto_oper)
+{
+	struct mlx5e_priv *priv    = mlx5i_epriv(netdev);
+	struct mlx5_core_dev *mdev = priv->mdev;
+	u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
+	int ret;
+
+	ret = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_IB, 1);
+	if (ret)
+		return ret;
+
+	*ib_link_width_oper = MLX5_GET(ptys_reg, out, ib_link_width_oper);
+	*ib_proto_oper      = MLX5_GET(ptys_reg, out, ib_proto_oper);
+
+	return 0;
+}
+
+static int mlx5i_get_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
+{
+	u16 ib_link_width_oper;
+	u16 ib_proto_oper;
+	int speed, ret;
+
+	ret = mlx5i_get_port_settings(netdev,
+				      &ib_link_width_oper,
+				      &ib_proto_oper);
+	if (ret)
+		return ret;
+
+	speed = mlx5i_get_speed_settings(ib_link_width_oper, ib_proto_oper);
+	if (speed < 0)
+		return -EINVAL;
+
+	ecmd->duplex = DUPLEX_FULL;
+	ecmd->port = PORT_OTHER;// FIXME: till define IB port type 
+	ecmd->phy_address = 255;
+	ecmd->autoneg = AUTONEG_DISABLE;
+
+	ethtool_cmd_speed_set(ecmd, speed);
+
+	return 0;
+}
+#endif
+
 static u32 mlx5i_flow_type_mask(u32 flow_type)
 {
 	return flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
@@ -268,9 +348,11 @@ static int mlx5i_get_rxnfc(struct net_de
 }
 
 const struct ethtool_ops mlx5i_ethtool_ops = {
+#ifdef HAVE_SUPPORTED_COALESCE_PARAM
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
 				     ETHTOOL_COALESCE_MAX_FRAMES |
 				     ETHTOOL_COALESCE_USE_ADAPTIVE,
+#endif
 	.get_drvinfo        = mlx5i_get_drvinfo,
 	.get_strings        = mlx5i_get_strings,
 	.get_sset_count     = mlx5i_get_sset_count,
@@ -286,11 +368,19 @@ const struct ethtool_ops mlx5i_ethtool_o
 	.get_rxnfc          = mlx5i_get_rxnfc,
 	.set_rxnfc          = mlx5i_set_rxnfc,
 	.get_link_ksettings = mlx5i_get_link_ksettings,
-	.get_link           = ethtool_op_get_link,
+#ifdef HAVE_ETHTOOL_GET_SET_SETTINGS
+	.get_settings       = mlx5i_get_settings,
+#endif
+ 	.get_link           = ethtool_op_get_link,
 };
 
 const struct ethtool_ops mlx5i_pkey_ethtool_ops = {
 	.get_drvinfo        = mlx5i_get_drvinfo,
 	.get_link           = ethtool_op_get_link,
 	.get_ts_info        = mlx5i_get_ts_info,
+	.get_link_ksettings = mlx5i_get_link_ksettings,
+#ifdef HAVE_ETHTOOL_GET_SET_SETTINGS
+	.get_settings	    = mlx5i_get_settings,
+#endif
 };
+
