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

Commit 3bae9db9 authored by David S. Miller's avatar David S. Miller
Browse files


Ben Hutchings says:

====================
1. Make EEH recovery work when using legacy interrupts, from Alexandre
   Rames.

2. Enable accelerated RFS for VLAN-tagged flows, from Andy Lutomirski.

3. Improve performance for non-TCP (and particularly UDP) traffic, which
   regressed in 3.10 when we switched to always allocating paged RX
   buffers.  Partly by Jon Cooper.

4. Some minor bug fixes to IOMMU detection, timestamping capabilities,
   and IRQ cleanup on the probe failure path.

I've dropped the RX skb cache, which improved some benchmarks but
perhaps needs some reworking to be more generally useful.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6541aa52 636d73da
Loading
Loading
Loading
Loading
+6 −34
Original line number Diff line number Diff line
@@ -21,8 +21,8 @@
#include <linux/ethtool.h>
#include <linux/topology.h>
#include <linux/gfp.h>
#include <linux/cpu_rmap.h>
#include <linux/aer.h>
#include <linux/interrupt.h>
#include "net_driver.h"
#include "efx.h"
#include "nic.h"
@@ -1283,29 +1283,6 @@ static unsigned int efx_wanted_parallelism(struct efx_nic *efx)
	return count;
}

static int
efx_init_rx_cpu_rmap(struct efx_nic *efx, struct msix_entry *xentries)
{
#ifdef CONFIG_RFS_ACCEL
	unsigned int i;
	int rc;

	efx->net_dev->rx_cpu_rmap = alloc_irq_cpu_rmap(efx->n_rx_channels);
	if (!efx->net_dev->rx_cpu_rmap)
		return -ENOMEM;
	for (i = 0; i < efx->n_rx_channels; i++) {
		rc = irq_cpu_rmap_add(efx->net_dev->rx_cpu_rmap,
				      xentries[i].vector);
		if (rc) {
			free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
			efx->net_dev->rx_cpu_rmap = NULL;
			return rc;
		}
	}
#endif
	return 0;
}

/* Probe the number and type of interrupts we are able to obtain, and
 * the resulting numbers of channels and RX queues.
 */
@@ -1359,11 +1336,6 @@ static int efx_probe_interrupts(struct efx_nic *efx)
				efx->n_tx_channels = n_channels;
				efx->n_rx_channels = n_channels;
			}
			rc = efx_init_rx_cpu_rmap(efx, xentries);
			if (rc) {
				pci_disable_msix(efx->pci_dev);
				return rc;
			}
			for (i = 0; i < efx->n_channels; i++)
				efx_get_channel(efx, i)->irq =
					xentries[i].vector;
@@ -1427,6 +1399,10 @@ static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq)

	BUG_ON(efx->state == STATE_DISABLED);

	if (efx->eeh_disabled_legacy_irq) {
		enable_irq(efx->legacy_irq);
		efx->eeh_disabled_legacy_irq = false;
	}
	if (efx->legacy_irq)
		efx->legacy_irq_enabled = true;
	efx_nic_enable_interrupts(efx);
@@ -2365,7 +2341,7 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
 * Returns 0 if the recovery mechanisms are unsuccessful.
 * Returns a non-zero value otherwise.
 */
static int efx_try_recovery(struct efx_nic *efx)
int efx_try_recovery(struct efx_nic *efx)
{
#ifdef CONFIG_EEH
	/* A PCI error can occur and not be seen by EEH because nothing
@@ -2603,10 +2579,6 @@ static void efx_pci_remove_main(struct efx_nic *efx)
	BUG_ON(efx->state == STATE_READY);
	cancel_work_sync(&efx->reset_work);

#ifdef CONFIG_RFS_ACCEL
	free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
	efx->net_dev->rx_cpu_rmap = NULL;
#endif
	efx_stop_interrupts(efx, false);
	efx_nic_fini_interrupt(efx);
	efx_fini_port(efx);
+1 −0
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ extern const struct ethtool_ops efx_ethtool_ops;
extern int efx_reset(struct efx_nic *efx, enum reset_type method);
extern void efx_reset_down(struct efx_nic *efx, enum reset_type method);
extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok);
extern int efx_try_recovery(struct efx_nic *efx);

/* Global */
extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
+15 −1
Original line number Diff line number Diff line
@@ -1114,6 +1114,20 @@ static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,
	return 0;
}

int efx_ethtool_get_ts_info(struct net_device *net_dev,
			    struct ethtool_ts_info *ts_info)
{
	struct efx_nic *efx = netdev_priv(net_dev);

	/* Software capabilities */
	ts_info->so_timestamping = (SOF_TIMESTAMPING_RX_SOFTWARE |
				    SOF_TIMESTAMPING_SOFTWARE);
	ts_info->phc_index = -1;

	efx_ptp_get_ts_info(efx, ts_info);
	return 0;
}

static int efx_ethtool_get_module_eeprom(struct net_device *net_dev,
					 struct ethtool_eeprom *ee,
					 u8 *data)
@@ -1176,7 +1190,7 @@ const struct ethtool_ops efx_ethtool_ops = {
	.get_rxfh_indir_size	= efx_ethtool_get_rxfh_indir_size,
	.get_rxfh_indir		= efx_ethtool_get_rxfh_indir,
	.set_rxfh_indir		= efx_ethtool_set_rxfh_indir,
	.get_ts_info		= efx_ptp_get_ts_info,
	.get_ts_info		= efx_ethtool_get_ts_info,
	.get_module_info	= efx_ethtool_get_module_info,
	.get_module_eeprom	= efx_ethtool_get_module_eeprom,
};
+14 −1
Original line number Diff line number Diff line
@@ -1185,9 +1185,22 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,

	nhoff = skb_network_offset(skb);

	if (skb->protocol != htons(ETH_P_IP))
	if (skb->protocol == htons(ETH_P_8021Q)) {
		EFX_BUG_ON_PARANOID(skb_headlen(skb) <
				    nhoff + sizeof(struct vlan_hdr));
		if (((const struct vlan_hdr *)skb->data + nhoff)->
		    h_vlan_encapsulated_proto != htons(ETH_P_IP))
			return -EPROTONOSUPPORT;

		/* This is IP over 802.1q VLAN.  We can't filter on the
		 * IP 5-tuple and the vlan together, so just strip the
		 * vlan header and filter on the IP part.
		 */
		nhoff += sizeof(struct vlan_hdr);
	} else if (skb->protocol != htons(ETH_P_IP)) {
		return -EPROTONOSUPPORT;
	}

	/* RFS must validate the IP header length before calling us */
	EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
	ip = (const struct iphdr *)(skb->data + nhoff);
+2 −0
Original line number Diff line number Diff line
@@ -243,6 +243,7 @@ struct efx_rx_buffer {
#define EFX_RX_BUF_LAST_IN_PAGE	0x0001
#define EFX_RX_PKT_CSUMMED	0x0002
#define EFX_RX_PKT_DISCARD	0x0004
#define EFX_RX_PKT_TCP		0x0040

/**
 * struct efx_rx_page_state - Page-based rx buffer state
@@ -788,6 +789,7 @@ struct efx_nic {
	const struct efx_nic_type *type;
	int legacy_irq;
	bool legacy_irq_enabled;
	bool eeh_disabled_legacy_irq;
	struct workqueue_struct *workqueue;
	char workqueue_name[16];
	struct work_struct reset_work;
Loading