Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92ab6407 authored by Yana Esina's avatar Yana Esina Committed by David S. Miller
Browse files

net: aquantia: implement EEE support



Support of Energy-Efficient Ethernet to aQuantia NIC's via ethtool
(according to the IEEE 802.3az specifications)

Signed-off-by: default avatarYana Esina <yana.esina@aquantia.com>
Signed-off-by: default avatarNikita Danilov <nikita.danilov@aquantia.com>
Tested-by: default avatarNikita Danilov <nikita.danilov@aquantia.com>
Signed-off-by: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a0da96c0
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -57,4 +57,9 @@
#define AQ_NIC_RATE_1G         BIT(4)
#define AQ_NIC_RATE_100M       BIT(5)

#define AQ_NIC_RATE_EEE_10G	BIT(6)
#define AQ_NIC_RATE_EEE_5G	BIT(7)
#define AQ_NIC_RATE_EEE_2GS	BIT(8)
#define AQ_NIC_RATE_EEE_1G	BIT(9)

#endif /* AQ_COMMON_H */
+77 −0
Original line number Diff line number Diff line
@@ -315,6 +315,81 @@ static int aq_ethtool_set_wol(struct net_device *ndev,
	return err;
}

static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed)
{
	u32 rate = 0;

	if (speed & AQ_NIC_RATE_EEE_10G)
		rate |= SUPPORTED_10000baseT_Full;

	if (speed & AQ_NIC_RATE_EEE_2GS)
		rate |= SUPPORTED_2500baseX_Full;

	if (speed & AQ_NIC_RATE_EEE_1G)
		rate |= SUPPORTED_1000baseT_Full;

	return rate;
}

static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
{
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	u32 rate, supported_rates;
	int err = 0;

	if (!aq_nic->aq_fw_ops->get_eee_rate)
		return -EOPNOTSUPP;

	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
					      &supported_rates);
	if (err < 0)
		return err;

	eee->supported = eee_mask_to_ethtool_mask(supported_rates);

	if (aq_nic->aq_nic_cfg.eee_speeds)
		eee->advertised = eee->supported;

	eee->lp_advertised = eee_mask_to_ethtool_mask(rate);

	eee->eee_enabled = !!eee->advertised;

	eee->tx_lpi_enabled = eee->eee_enabled;
	if (eee->advertised & eee->lp_advertised)
		eee->eee_active = true;

	return 0;
}

static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
{
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	u32 rate, supported_rates;
	struct aq_nic_cfg_s *cfg;
	int err = 0;

	cfg = aq_nic_get_cfg(aq_nic);

	if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
		     !aq_nic->aq_fw_ops->set_eee_rate))
		return -EOPNOTSUPP;

	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
					      &supported_rates);
	if (err < 0)
		return err;

	if (eee->eee_enabled) {
		rate = supported_rates;
		cfg->eee_speeds = rate;
	} else {
		rate = 0;
		cfg->eee_speeds = 0;
	}

	return aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
}

static int aq_ethtool_nway_reset(struct net_device *ndev)
{
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
@@ -438,6 +513,8 @@ const struct ethtool_ops aq_ethtool_ops = {
	.nway_reset          = aq_ethtool_nway_reset,
	.get_ringparam       = aq_get_ringparam,
	.set_ringparam       = aq_set_ringparam,
	.get_eee             = aq_ethtool_get_eee,
	.set_eee             = aq_ethtool_set_eee,
	.get_pauseparam      = aq_ethtool_get_pauseparam,
	.set_pauseparam      = aq_ethtool_set_pauseparam,
	.get_rxfh_key_size   = aq_ethtool_get_rss_key_size,
+5 −0
Original line number Diff line number Diff line
@@ -230,6 +230,11 @@ struct aq_fw_ops {

	int (*set_power)(struct aq_hw_s *self, unsigned int power_state,
			 u8 *mac);

	int (*set_eee_rate)(struct aq_hw_s *self, u32 speed);

	int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate,
			    u32 *supported_rates);
};

#endif /* AQ_HW_H */
+1 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ struct aq_nic_cfg_s {
	bool is_lro;
	u8  tcs;
	struct aq_rss_parameters aq_rss;
	u32 eee_speeds;
};

#define AQ_NIC_FLAG_STARTED     0x00000004U
+2 −0
Original line number Diff line number Diff line
@@ -916,5 +916,7 @@ const struct aq_fw_ops aq_fw_1x_ops = {
	.update_link_status = hw_atl_utils_mpi_get_link_status,
	.update_stats = hw_atl_utils_update_stats,
	.set_power = aq_fw1x_set_power,
	.set_eee_rate = NULL,
	.get_eee_rate = NULL,
	.set_flow_control = NULL,
};
Loading