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

Commit 43ebf97f authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'aquantia-fixes'



Igor Russkikh says:

====================
net: aquantia: Atlantic driver 10/2017 updates

This patchset fixes various issues in driver,
improves parameters for better performance on 10Gbit link
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 197df02c 417a3ae4
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -22,8 +22,12 @@


#define AQ_CFG_FORCE_LEGACY_INT 0U
#define AQ_CFG_FORCE_LEGACY_INT 0U


#define AQ_CFG_IS_INTERRUPT_MODERATION_DEF   1U
#define AQ_CFG_INTERRUPT_MODERATION_OFF		0
#define AQ_CFG_INTERRUPT_MODERATION_RATE_DEF 0xFFFFU
#define AQ_CFG_INTERRUPT_MODERATION_ON		1
#define AQ_CFG_INTERRUPT_MODERATION_AUTO	0xFFFFU

#define AQ_CFG_INTERRUPT_MODERATION_USEC_MAX (0x1FF * 2)

#define AQ_CFG_IRQ_MASK                      0x1FFU
#define AQ_CFG_IRQ_MASK                      0x1FFU


#define AQ_CFG_VECS_MAX   8U
#define AQ_CFG_VECS_MAX   8U
+99 −58
Original line number Original line Diff line number Diff line
@@ -56,10 +56,6 @@ aq_ethtool_set_link_ksettings(struct net_device *ndev,
	return aq_nic_set_link_ksettings(aq_nic, cmd);
	return aq_nic_set_link_ksettings(aq_nic, cmd);
}
}


/* there "5U" is number of queue[#] stats lines (InPackets+...+InErrors) */
static const unsigned int aq_ethtool_stat_queue_lines = 5U;
static const unsigned int aq_ethtool_stat_queue_chars =
	5U * ETH_GSTRING_LEN;
static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
	"InPackets",
	"InPackets",
	"InUCast",
	"InUCast",
@@ -83,56 +79,26 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
	"InOctetsDma",
	"InOctetsDma",
	"OutOctetsDma",
	"OutOctetsDma",
	"InDroppedDma",
	"InDroppedDma",
	"Queue[0] InPackets",
};
	"Queue[0] OutPackets",

	"Queue[0] InJumboPackets",
static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
	"Queue[0] InLroPackets",
	"Queue[%d] InPackets",
	"Queue[0] InErrors",
	"Queue[%d] OutPackets",
	"Queue[1] InPackets",
	"Queue[%d] Restarts",
	"Queue[1] OutPackets",
	"Queue[%d] InJumboPackets",
	"Queue[1] InJumboPackets",
	"Queue[%d] InLroPackets",
	"Queue[1] InLroPackets",
	"Queue[%d] InErrors",
	"Queue[1] InErrors",
	"Queue[2] InPackets",
	"Queue[2] OutPackets",
	"Queue[2] InJumboPackets",
	"Queue[2] InLroPackets",
	"Queue[2] InErrors",
	"Queue[3] InPackets",
	"Queue[3] OutPackets",
	"Queue[3] InJumboPackets",
	"Queue[3] InLroPackets",
	"Queue[3] InErrors",
	"Queue[4] InPackets",
	"Queue[4] OutPackets",
	"Queue[4] InJumboPackets",
	"Queue[4] InLroPackets",
	"Queue[4] InErrors",
	"Queue[5] InPackets",
	"Queue[5] OutPackets",
	"Queue[5] InJumboPackets",
	"Queue[5] InLroPackets",
	"Queue[5] InErrors",
	"Queue[6] InPackets",
	"Queue[6] OutPackets",
	"Queue[6] InJumboPackets",
	"Queue[6] InLroPackets",
	"Queue[6] InErrors",
	"Queue[7] InPackets",
	"Queue[7] OutPackets",
	"Queue[7] InJumboPackets",
	"Queue[7] InLroPackets",
	"Queue[7] InErrors",
};
};


static void aq_ethtool_stats(struct net_device *ndev,
static void aq_ethtool_stats(struct net_device *ndev,
			     struct ethtool_stats *stats, u64 *data)
			     struct ethtool_stats *stats, u64 *data)
{
{
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);


/* ASSERT: Need add lines to aq_ethtool_stat_names if AQ_CFG_VECS_MAX > 8 */
	memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) +
	BUILD_BUG_ON(AQ_CFG_VECS_MAX > 8);
				ARRAY_SIZE(aq_ethtool_queue_stat_names) *
	memset(data, 0, ARRAY_SIZE(aq_ethtool_stat_names) * sizeof(u64));
				cfg->vecs) * sizeof(u64));
	aq_nic_get_stats(aq_nic, data);
	aq_nic_get_stats(aq_nic, data);
}
}


@@ -154,8 +120,8 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,


	strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
	strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
		sizeof(drvinfo->bus_info));
		sizeof(drvinfo->bus_info));
	drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) -
	drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
		(AQ_CFG_VECS_MAX - cfg->vecs) * aq_ethtool_stat_queue_lines;
		cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
	drvinfo->testinfo_len = 0;
	drvinfo->testinfo_len = 0;
	drvinfo->regdump_len = regs_count;
	drvinfo->regdump_len = regs_count;
	drvinfo->eedump_len = 0;
	drvinfo->eedump_len = 0;
@@ -164,14 +130,25 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
static void aq_ethtool_get_strings(struct net_device *ndev,
static void aq_ethtool_get_strings(struct net_device *ndev,
				   u32 stringset, u8 *data)
				   u32 stringset, u8 *data)
{
{
	int i, si;
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);

	u8 *p = data;
	if (stringset == ETH_SS_STATS)

		memcpy(data, *aq_ethtool_stat_names,
	if (stringset == ETH_SS_STATS) {
		       sizeof(aq_ethtool_stat_names) -
		memcpy(p, *aq_ethtool_stat_names,
		       (AQ_CFG_VECS_MAX - cfg->vecs) *
		       sizeof(aq_ethtool_stat_names));
		       aq_ethtool_stat_queue_chars);
		p = p + sizeof(aq_ethtool_stat_names);
		for (i = 0; i < cfg->vecs; i++) {
			for (si = 0;
				si < ARRAY_SIZE(aq_ethtool_queue_stat_names);
				si++) {
				snprintf(p, ETH_GSTRING_LEN,
					 aq_ethtool_queue_stat_names[si], i);
				p += ETH_GSTRING_LEN;
			}
		}
	}
}
}


static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
@@ -182,9 +159,8 @@ static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)


	switch (stringset) {
	switch (stringset) {
	case ETH_SS_STATS:
	case ETH_SS_STATS:
		ret = ARRAY_SIZE(aq_ethtool_stat_names) -
		ret = ARRAY_SIZE(aq_ethtool_stat_names) +
			(AQ_CFG_VECS_MAX - cfg->vecs) *
			cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
			aq_ethtool_stat_queue_lines;
		break;
		break;
	default:
	default:
		ret = -EOPNOTSUPP;
		ret = -EOPNOTSUPP;
@@ -245,6 +221,69 @@ static int aq_ethtool_get_rxnfc(struct net_device *ndev,
	return err;
	return err;
}
}


int aq_ethtool_get_coalesce(struct net_device *ndev,
			    struct ethtool_coalesce *coal)
{
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);

	if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
	    cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
		coal->rx_coalesce_usecs = cfg->rx_itr;
		coal->tx_coalesce_usecs = cfg->tx_itr;
		coal->rx_max_coalesced_frames = 0;
		coal->tx_max_coalesced_frames = 0;
	} else {
		coal->rx_coalesce_usecs = 0;
		coal->tx_coalesce_usecs = 0;
		coal->rx_max_coalesced_frames = 1;
		coal->tx_max_coalesced_frames = 1;
	}
	return 0;
}

int aq_ethtool_set_coalesce(struct net_device *ndev,
			    struct ethtool_coalesce *coal)
{
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);

	/* This is not yet supported
	 */
	if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce)
		return -EOPNOTSUPP;

	/* Atlantic only supports timing based coalescing
	 */
	if (coal->rx_max_coalesced_frames > 1 ||
	    coal->rx_coalesce_usecs_irq ||
	    coal->rx_max_coalesced_frames_irq)
		return -EOPNOTSUPP;

	if (coal->tx_max_coalesced_frames > 1 ||
	    coal->tx_coalesce_usecs_irq ||
	    coal->tx_max_coalesced_frames_irq)
		return -EOPNOTSUPP;

	/* We do not support frame counting. Check this
	 */
	if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
		return -EOPNOTSUPP;
	if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
		return -EOPNOTSUPP;

	if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
	    coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
		return -EINVAL;

	cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;

	cfg->rx_itr = coal->rx_coalesce_usecs;
	cfg->tx_itr = coal->tx_coalesce_usecs;

	return aq_nic_update_interrupt_moderation_settings(aq_nic);
}

const struct ethtool_ops aq_ethtool_ops = {
const struct ethtool_ops aq_ethtool_ops = {
	.get_link            = aq_ethtool_get_link,
	.get_link            = aq_ethtool_get_link,
	.get_regs_len        = aq_ethtool_get_regs_len,
	.get_regs_len        = aq_ethtool_get_regs_len,
@@ -259,4 +298,6 @@ const struct ethtool_ops aq_ethtool_ops = {
	.get_ethtool_stats   = aq_ethtool_stats,
	.get_ethtool_stats   = aq_ethtool_stats,
	.get_link_ksettings  = aq_ethtool_get_link_ksettings,
	.get_link_ksettings  = aq_ethtool_get_link_ksettings,
	.set_link_ksettings  = aq_ethtool_set_link_ksettings,
	.set_link_ksettings  = aq_ethtool_set_link_ksettings,
	.get_coalesce	     = aq_ethtool_get_coalesce,
	.set_coalesce	     = aq_ethtool_set_coalesce,
};
};
+3 −2
Original line number Original line Diff line number Diff line
@@ -151,8 +151,7 @@ struct aq_hw_ops {
				     [ETH_ALEN],
				     [ETH_ALEN],
				     u32 count);
				     u32 count);


	int (*hw_interrupt_moderation_set)(struct aq_hw_s *self,
	int (*hw_interrupt_moderation_set)(struct aq_hw_s *self);
					   bool itr_enabled);


	int (*hw_rss_set)(struct aq_hw_s *self,
	int (*hw_rss_set)(struct aq_hw_s *self,
			  struct aq_rss_parameters *rss_params);
			  struct aq_rss_parameters *rss_params);
@@ -163,6 +162,8 @@ struct aq_hw_ops {
	int (*hw_get_regs)(struct aq_hw_s *self,
	int (*hw_get_regs)(struct aq_hw_s *self,
			   struct aq_hw_caps_s *aq_hw_caps, u32 *regs_buff);
			   struct aq_hw_caps_s *aq_hw_caps, u32 *regs_buff);


	int (*hw_update_stats)(struct aq_hw_s *self);

	int (*hw_get_hw_stats)(struct aq_hw_s *self, u64 *data,
	int (*hw_get_hw_stats)(struct aq_hw_s *self, u64 *data,
			       unsigned int *p_count);
			       unsigned int *p_count);


+30 −9
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@
#include "aq_pci_func.h"
#include "aq_pci_func.h"
#include "aq_nic_internal.h"
#include "aq_nic_internal.h"


#include <linux/moduleparam.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/timer.h>
#include <linux/timer.h>
@@ -24,6 +25,18 @@
#include <linux/tcp.h>
#include <linux/tcp.h>
#include <net/ip.h>
#include <net/ip.h>


static unsigned int aq_itr = AQ_CFG_INTERRUPT_MODERATION_AUTO;
module_param_named(aq_itr, aq_itr, uint, 0644);
MODULE_PARM_DESC(aq_itr, "Interrupt throttling mode");

static unsigned int aq_itr_tx;
module_param_named(aq_itr_tx, aq_itr_tx, uint, 0644);
MODULE_PARM_DESC(aq_itr_tx, "TX interrupt throttle rate");

static unsigned int aq_itr_rx;
module_param_named(aq_itr_rx, aq_itr_rx, uint, 0644);
MODULE_PARM_DESC(aq_itr_rx, "RX interrupt throttle rate");

static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues)
static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues)
{
{
	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
@@ -61,9 +74,9 @@ static void aq_nic_cfg_init_defaults(struct aq_nic_s *self)


	cfg->is_polling = AQ_CFG_IS_POLLING_DEF;
	cfg->is_polling = AQ_CFG_IS_POLLING_DEF;


	cfg->is_interrupt_moderation = AQ_CFG_IS_INTERRUPT_MODERATION_DEF;
	cfg->itr = aq_itr;
	cfg->itr = cfg->is_interrupt_moderation ?
	cfg->tx_itr = aq_itr_tx;
		AQ_CFG_INTERRUPT_MODERATION_RATE_DEF : 0U;
	cfg->rx_itr = aq_itr_rx;


	cfg->is_rss = AQ_CFG_IS_RSS_DEF;
	cfg->is_rss = AQ_CFG_IS_RSS_DEF;
	cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF;
	cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF;
@@ -126,10 +139,12 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
	if (err)
	if (err)
		return err;
		return err;


	if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps)
	if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps) {
		pr_info("%s: link change old %d new %d\n",
		pr_info("%s: link change old %d new %d\n",
			AQ_CFG_DRV_NAME, self->link_status.mbps,
			AQ_CFG_DRV_NAME, self->link_status.mbps,
			self->aq_hw->aq_link_status.mbps);
			self->aq_hw->aq_link_status.mbps);
		aq_nic_update_interrupt_moderation_settings(self);
	}


	self->link_status = self->aq_hw->aq_link_status;
	self->link_status = self->aq_hw->aq_link_status;
	if (!netif_carrier_ok(self->ndev) && self->link_status.mbps) {
	if (!netif_carrier_ok(self->ndev) && self->link_status.mbps) {
@@ -164,8 +179,8 @@ static void aq_nic_service_timer_cb(unsigned long param)
	if (err)
	if (err)
		goto err_exit;
		goto err_exit;


	self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
	if (self->aq_hw_ops.hw_update_stats)
		    self->aq_nic_cfg.is_interrupt_moderation);
		self->aq_hw_ops.hw_update_stats(self->aq_hw);


	memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
	memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
	memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
	memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
@@ -334,6 +349,7 @@ struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev)
	}
	}
	if (netif_running(ndev))
	if (netif_running(ndev))
		netif_tx_disable(ndev);
		netif_tx_disable(ndev);
	netif_carrier_off(self->ndev);


	for (self->aq_vecs = 0; self->aq_vecs < self->aq_nic_cfg.vecs;
	for (self->aq_vecs = 0; self->aq_vecs < self->aq_nic_cfg.vecs;
		self->aq_vecs++) {
		self->aq_vecs++) {
@@ -421,9 +437,8 @@ int aq_nic_start(struct aq_nic_s *self)
	if (err < 0)
	if (err < 0)
		goto err_exit;
		goto err_exit;


	err = self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
	err = aq_nic_update_interrupt_moderation_settings(self);
			    self->aq_nic_cfg.is_interrupt_moderation);
	if (err)
	if (err < 0)
		goto err_exit;
		goto err_exit;
	setup_timer(&self->service_timer, &aq_nic_service_timer_cb,
	setup_timer(&self->service_timer, &aq_nic_service_timer_cb,
		    (unsigned long)self);
		    (unsigned long)self);
@@ -645,6 +660,11 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
	return err;
	return err;
}
}


int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self)
{
	return self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw);
}

int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags)
int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags)
{
{
	int err = 0;
	int err = 0;
@@ -899,6 +919,7 @@ int aq_nic_stop(struct aq_nic_s *self)
	unsigned int i = 0U;
	unsigned int i = 0U;


	netif_tx_disable(self->ndev);
	netif_tx_disable(self->ndev);
	netif_carrier_off(self->ndev);


	del_timer_sync(&self->service_timer);
	del_timer_sync(&self->service_timer);


+3 −1
Original line number Original line Diff line number Diff line
@@ -40,6 +40,8 @@ struct aq_nic_cfg_s {
	u32 vecs;		/* vecs==allocated irqs */
	u32 vecs;		/* vecs==allocated irqs */
	u32 irq_type;
	u32 irq_type;
	u32 itr;
	u32 itr;
	u16 rx_itr;
	u16 tx_itr;
	u32 num_rss_queues;
	u32 num_rss_queues;
	u32 mtu;
	u32 mtu;
	u32 ucp_0x364;
	u32 ucp_0x364;
@@ -49,7 +51,6 @@ struct aq_nic_cfg_s {
	u16 is_mc_list_enabled;
	u16 is_mc_list_enabled;
	u16 mc_list_count;
	u16 mc_list_count;
	bool is_autoneg;
	bool is_autoneg;
	bool is_interrupt_moderation;
	bool is_polling;
	bool is_polling;
	bool is_rss;
	bool is_rss;
	bool is_lro;
	bool is_lro;
@@ -104,5 +105,6 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self,
struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self);
struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self);
u32 aq_nic_get_fw_version(struct aq_nic_s *self);
u32 aq_nic_get_fw_version(struct aq_nic_s *self);
int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg);
int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg);
int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self);


#endif /* AQ_NIC_H */
#endif /* AQ_NIC_H */
Loading