Эх сурвалжийг харах

net: aquantia: Add renegotiate ethtool operation support

Adds ethtool -r|--negotiate operation support. It triggers special
control bit on FW interface causing FW to restart link negotiation.

Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: Anton Mikaev <amikaev@aquantia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Anton Mikaev 7 жил өмнө
parent
commit
b8d68b62d9

+ 14 - 0
drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c

@@ -285,6 +285,19 @@ static int aq_ethtool_set_coalesce(struct net_device *ndev,
 	return aq_nic_update_interrupt_moderation_settings(aq_nic);
 	return aq_nic_update_interrupt_moderation_settings(aq_nic);
 }
 }
 
 
+static int aq_ethtool_nway_reset(struct net_device *ndev)
+{
+	struct aq_nic_s *aq_nic = netdev_priv(ndev);
+
+	if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
+		return -EOPNOTSUPP;
+
+	if (netif_running(ndev))
+		return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
+
+	return 0;
+}
+
 static void aq_ethtool_get_pauseparam(struct net_device *ndev,
 static void aq_ethtool_get_pauseparam(struct net_device *ndev,
 				      struct ethtool_pauseparam *pause)
 				      struct ethtool_pauseparam *pause)
 {
 {
@@ -390,6 +403,7 @@ const struct ethtool_ops aq_ethtool_ops = {
 	.get_drvinfo         = aq_ethtool_get_drvinfo,
 	.get_drvinfo         = aq_ethtool_get_drvinfo,
 	.get_strings         = aq_ethtool_get_strings,
 	.get_strings         = aq_ethtool_get_strings,
 	.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
 	.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
+	.nway_reset          = aq_ethtool_nway_reset,
 	.get_ringparam       = aq_get_ringparam,
 	.get_ringparam       = aq_get_ringparam,
 	.set_ringparam       = aq_set_ringparam,
 	.set_ringparam       = aq_set_ringparam,
 	.get_pauseparam      = aq_ethtool_get_pauseparam,
 	.get_pauseparam      = aq_ethtool_get_pauseparam,

+ 2 - 0
drivers/net/ethernet/aquantia/atlantic/aq_hw.h

@@ -212,6 +212,8 @@ struct aq_fw_ops {
 
 
 	int (*reset)(struct aq_hw_s *self);
 	int (*reset)(struct aq_hw_s *self);
 
 
+	int (*renegotiate)(struct aq_hw_s *self);
+
 	int (*get_mac_permanent)(struct aq_hw_s *self, u8 *mac);
 	int (*get_mac_permanent)(struct aq_hw_s *self, u8 *mac);
 
 
 	int (*set_link_speed)(struct aq_hw_s *self, u32 speed);
 	int (*set_link_speed)(struct aq_hw_s *self, u32 speed);

+ 35 - 0
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h

@@ -239,6 +239,41 @@ enum hw_atl_fw2x_caps_hi {
 	CAPS_HI_TRANSACTION_ID,
 	CAPS_HI_TRANSACTION_ID,
 };
 };
 
 
+enum hw_atl_fw2x_ctrl {
+	CTRL_RESERVED1 = 0x00,
+	CTRL_RESERVED2,
+	CTRL_RESERVED3,
+	CTRL_PAUSE,
+	CTRL_ASYMMETRIC_PAUSE,
+	CTRL_RESERVED4,
+	CTRL_RESERVED5,
+	CTRL_RESERVED6,
+	CTRL_1GBASET_FD_EEE,
+	CTRL_2P5GBASET_FD_EEE,
+	CTRL_5GBASET_FD_EEE,
+	CTRL_10GBASET_FD_EEE,
+	CTRL_THERMAL_SHUTDOWN,
+	CTRL_PHY_LOGS,
+	CTRL_EEE_AUTO_DISABLE,
+	CTRL_PFC,
+	CTRL_WAKE_ON_LINK,
+	CTRL_CABLE_DIAG,
+	CTRL_TEMPERATURE,
+	CTRL_DOWNSHIFT,
+	CTRL_PTP_AVB,
+	CTRL_RESERVED7,
+	CTRL_LINK_DROP,
+	CTRL_SLEEP_PROXY,
+	CTRL_WOL,
+	CTRL_MAC_STOP,
+	CTRL_EXT_LOOPBACK,
+	CTRL_INT_LOOPBACK,
+	CTRL_RESERVED8,
+	CTRL_WOL_TIMER,
+	CTRL_STATISTICS,
+	CTRL_FORCE_RECONNECT,
+};
+
 struct aq_hw_s;
 struct aq_hw_s;
 struct aq_fw_ops;
 struct aq_fw_ops;
 struct aq_hw_caps_s;
 struct aq_hw_caps_s;

+ 12 - 0
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c

@@ -215,6 +215,17 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
 	return hw_atl_utils_update_stats(self);
 	return hw_atl_utils_update_stats(self);
 }
 }
 
 
+static int aq_fw2x_renegotiate(struct aq_hw_s *self)
+{
+	u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
+
+	mpi_opts |= BIT(CTRL_FORCE_RECONNECT);
+
+	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
+
+	return 0;
+}
+
 static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
 static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
 {
 {
 	u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
 	u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
@@ -230,6 +241,7 @@ const struct aq_fw_ops aq_fw_2x_ops = {
 	.init = aq_fw2x_init,
 	.init = aq_fw2x_init,
 	.deinit = aq_fw2x_deinit,
 	.deinit = aq_fw2x_deinit,
 	.reset = NULL,
 	.reset = NULL,
+	.renegotiate = aq_fw2x_renegotiate,
 	.get_mac_permanent = aq_fw2x_get_mac_permanent,
 	.get_mac_permanent = aq_fw2x_get_mac_permanent,
 	.set_link_speed = aq_fw2x_set_link_speed,
 	.set_link_speed = aq_fw2x_set_link_speed,
 	.set_state = aq_fw2x_set_state,
 	.set_state = aq_fw2x_set_state,