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

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


Jeff Kirsher says:

====================
40GbE Intel Wired LAN Driver Updates 2015-12-03

This series contains updates to i40e and i40evf only.

Mitch updates the i40evf driver by increasing the maximum number of queues,
since future devices will allow for more queue pairs.  Cleans up a
duplicate printing of the driver info string done in init, since it is
already done in probe.  Cleaned up the several allocations which did
not need to be at atomic level, where GFP_KERNEL would work just fine.
Then makes i40e_sync_vsi_filters() a more mature function, make having
a common exit point so it will properly release the busy lock on the VSI
and propagate errors to the callers.  Then does some whitespace
housekeeping in i40evf.

Kiran moves and updates the detection/recovery of transmit queue hang code
to service_task from tx_timeout function.  Also fixed memory leak when
users program flow-director filter using ethtool (sideband filter
programming), the cause being the check of 'tx_buffer->skb' was preventing
'raw_buf' from being freed as part of the cleanup.

Jesse enabled the ability to turn off/on packet split using ethtool priv
flags.  Then does some housekeeping for both the i40e and i40evf drivers
which includes: remove unused/useless code, correct whitespace, remove
duplicate #include, fix incorrect comment, etc...

Neerav cleans up functions to gather Flow Control Rx XOFF stats, since
the recent change in the driver logic for checking transmit hang has been
moved, so these functions do not do anything meaningful any longer.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c5b6c3ee 4eeb1fff
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -269,17 +269,6 @@ config I40E
	  To compile this driver as a module, choose M here. The module
	  will be called i40e.

config I40E_VXLAN
	bool "Virtual eXtensible Local Area Network Support"
	default n
	depends on I40E && VXLAN && !(I40E=y && VXLAN=m)
	---help---
	  This allows one to create VXLAN virtual interfaces that provide
	  Layer 2 Networks over Layer 3 Networks. VXLAN is often used
	  to tunnel virtual network infrastructure in virtualized environments.
	  Say Y here if you want to use Virtual eXtensible Local Area Network
	  (VXLAN) in the driver.

config I40E_DCB
	bool "Data Center Bridging (DCB) Support"
	default n
+8 −7
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@
#include <linux/string.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/sctp.h>
#include <linux/pkt_sched.h>
#include <linux/ipv6.h>
@@ -104,6 +103,7 @@
#define I40E_PRIV_FLAGS_LINKPOLL_FLAG	BIT(1)
#define I40E_PRIV_FLAGS_FD_ATR		BIT(2)
#define I40E_PRIV_FLAGS_VEB_STATS	BIT(3)
#define I40E_PRIV_FLAGS_PS		BIT(4)

#define I40E_NVM_VERSION_LO_SHIFT  0
#define I40E_NVM_VERSION_LO_MASK   (0xff << I40E_NVM_VERSION_LO_SHIFT)
@@ -281,7 +281,7 @@ struct i40e_pf {
	u32 fd_atr_cnt;
	u32 fd_tcp_rule;

#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN)
	__be16  vxlan_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
	u16 pending_vxlan_bitmap;

@@ -322,9 +322,7 @@ struct i40e_pf {
#define I40E_FLAG_FD_ATR_ENABLED		BIT_ULL(22)
#define I40E_FLAG_PTP				BIT_ULL(25)
#define I40E_FLAG_MFP_ENABLED			BIT_ULL(26)
#ifdef CONFIG_I40E_VXLAN
#define I40E_FLAG_VXLAN_FILTER_SYNC		BIT_ULL(27)
#endif
#define I40E_FLAG_PORT_ID_VALID			BIT_ULL(28)
#define I40E_FLAG_DCB_CAPABLE			BIT_ULL(29)
#define I40E_FLAG_RSS_AQ_CAPABLE		BIT_ULL(31)
@@ -579,6 +577,9 @@ struct i40e_q_vector {

	u8 num_ringpairs;	/* total number of ring pairs in vector */

#define I40E_Q_VECTOR_HUNG_DETECT 0 /* Bit Index for hung detection logic */
	unsigned long hung_detected; /* Set/Reset for hung_detection logic */

	cpumask_t affinity_mask;
	struct rcu_head rcu;	/* to avoid race with update stats on free */
	char name[I40E_INT_NAME_STR_LEN];
@@ -606,8 +607,8 @@ static inline char *i40e_nvm_version_str(struct i40e_hw *hw)

	full_ver = hw->nvm.oem_ver;
	ver = (u8)(full_ver >> I40E_OEM_VER_SHIFT);
	build = (u16)((full_ver >> I40E_OEM_VER_BUILD_SHIFT)
		 & I40E_OEM_VER_BUILD_MASK);
	build = (u16)((full_ver >> I40E_OEM_VER_BUILD_SHIFT) &
		 I40E_OEM_VER_BUILD_MASK);
	patch = (u8)(full_ver & I40E_OEM_VER_PATCH_MASK);

	snprintf(buf, sizeof(buf),
@@ -715,7 +716,7 @@ struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid,
void i40e_veb_release(struct i40e_veb *veb);

int i40e_veb_config_tc(struct i40e_veb *veb, u8 enabled_tc);
i40e_status i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid);
int i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid);
void i40e_vsi_remove_pvid(struct i40e_vsi *vsi);
void i40e_vsi_reset_stats(struct i40e_vsi *vsi);
void i40e_pf_reset_stats(struct i40e_pf *pf);
+27 −0
Original line number Diff line number Diff line
@@ -231,6 +231,7 @@ static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
	"LinkPolling",
	"flow-director-atr",
	"veb-stats",
	"packet-split",
};

#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings)
@@ -2709,6 +2710,8 @@ static u32 i40e_get_priv_flags(struct net_device *dev)
		I40E_PRIV_FLAGS_FD_ATR : 0;
	ret_flags |= pf->flags & I40E_FLAG_VEB_STATS_ENABLED ?
		I40E_PRIV_FLAGS_VEB_STATS : 0;
	ret_flags |= pf->flags & I40E_FLAG_RX_PS_ENABLED ?
		I40E_PRIV_FLAGS_PS : 0;

	return ret_flags;
}
@@ -2723,6 +2726,26 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
	struct i40e_netdev_priv *np = netdev_priv(dev);
	struct i40e_vsi *vsi = np->vsi;
	struct i40e_pf *pf = vsi->back;
	bool reset_required = false;

	/* NOTE: MFP is not settable */

	/* allow the user to control the method of receive
	 * buffer DMA, whether the packet is split at header
	 * boundaries into two separate buffers.  In some cases
	 * one routine or the other will perform better.
	 */
	if ((flags & I40E_PRIV_FLAGS_PS) &&
	    !(pf->flags & I40E_FLAG_RX_PS_ENABLED)) {
		pf->flags |= I40E_FLAG_RX_PS_ENABLED;
		pf->flags &= ~I40E_FLAG_RX_1BUF_ENABLED;
		reset_required = true;
	} else if (!(flags & I40E_PRIV_FLAGS_PS) &&
		   (pf->flags & I40E_FLAG_RX_PS_ENABLED)) {
		pf->flags &= ~I40E_FLAG_RX_PS_ENABLED;
		pf->flags |= I40E_FLAG_RX_1BUF_ENABLED;
		reset_required = true;
	}

	if (flags & I40E_PRIV_FLAGS_LINKPOLL_FLAG)
		pf->flags |= I40E_FLAG_LINK_POLLING_ENABLED;
@@ -2745,6 +2768,10 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
	else
		pf->flags &= ~I40E_FLAG_VEB_STATS_ENABLED;

	/* if needed, issue reset to cause things to take effect */
	if (reset_required)
		i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED));

	return 0;
}

+112 −128
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@
/* Local includes */
#include "i40e.h"
#include "i40e_diag.h"
#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN)
#include <net/vxlan.h>
#endif

@@ -39,7 +39,7 @@ static const char i40e_driver_string[] =

#define DRV_VERSION_MAJOR 1
#define DRV_VERSION_MINOR 4
#define DRV_VERSION_BUILD 4
#define DRV_VERSION_BUILD 7
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
	     __stringify(DRV_VERSION_MINOR) "." \
	     __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -791,75 +791,6 @@ static void i40e_update_fcoe_stats(struct i40e_vsi *vsi)
}

#endif
/**
 * i40e_update_link_xoff_rx - Update XOFF received in link flow control mode
 * @pf: the corresponding PF
 *
 * Update the Rx XOFF counter (PAUSE frames) in link flow control mode
 **/
static void i40e_update_link_xoff_rx(struct i40e_pf *pf)
{
	struct i40e_hw_port_stats *osd = &pf->stats_offsets;
	struct i40e_hw_port_stats *nsd = &pf->stats;
	struct i40e_hw *hw = &pf->hw;
	u64 xoff = 0;

	if ((hw->fc.current_mode != I40E_FC_FULL) &&
	    (hw->fc.current_mode != I40E_FC_RX_PAUSE))
		return;

	xoff = nsd->link_xoff_rx;
	i40e_stat_update32(hw, I40E_GLPRT_LXOFFRXC(hw->port),
			   pf->stat_offsets_loaded,
			   &osd->link_xoff_rx, &nsd->link_xoff_rx);

	/* No new LFC xoff rx */
	if (!(nsd->link_xoff_rx - xoff))
		return;

}

/**
 * i40e_update_prio_xoff_rx - Update XOFF received in PFC mode
 * @pf: the corresponding PF
 *
 * Update the Rx XOFF counter (PAUSE frames) in PFC mode
 **/
static void i40e_update_prio_xoff_rx(struct i40e_pf *pf)
{
	struct i40e_hw_port_stats *osd = &pf->stats_offsets;
	struct i40e_hw_port_stats *nsd = &pf->stats;
	bool xoff[I40E_MAX_TRAFFIC_CLASS] = {false};
	struct i40e_dcbx_config *dcb_cfg;
	struct i40e_hw *hw = &pf->hw;
	u16 i;
	u8 tc;

	dcb_cfg = &hw->local_dcbx_config;

	/* Collect Link XOFF stats when PFC is disabled */
	if (!dcb_cfg->pfc.pfcenable) {
		i40e_update_link_xoff_rx(pf);
		return;
	}

	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
		u64 prio_xoff = nsd->priority_xoff_rx[i];

		i40e_stat_update32(hw, I40E_GLPRT_PXOFFRXC(hw->port, i),
				   pf->stat_offsets_loaded,
				   &osd->priority_xoff_rx[i],
				   &nsd->priority_xoff_rx[i]);

		/* No new PFC xoff rx */
		if (!(nsd->priority_xoff_rx[i] - prio_xoff))
			continue;
		/* Get the TC for given priority */
		tc = dcb_cfg->etscfg.prioritytable[i];
		xoff[tc] = true;
	}
}

/**
 * i40e_update_vsi_stats - Update the vsi statistics counters.
 * @vsi: the VSI to be updated
@@ -1054,12 +985,18 @@ static void i40e_update_pf_stats(struct i40e_pf *pf)
	i40e_stat_update32(hw, I40E_GLPRT_LXONTXC(hw->port),
			   pf->stat_offsets_loaded,
			   &osd->link_xon_tx, &nsd->link_xon_tx);
	i40e_update_prio_xoff_rx(pf);  /* handles I40E_GLPRT_LXOFFRXC */
	i40e_stat_update32(hw, I40E_GLPRT_LXOFFRXC(hw->port),
			   pf->stat_offsets_loaded,
			   &osd->link_xoff_rx, &nsd->link_xoff_rx);
	i40e_stat_update32(hw, I40E_GLPRT_LXOFFTXC(hw->port),
			   pf->stat_offsets_loaded,
			   &osd->link_xoff_tx, &nsd->link_xoff_tx);

	for (i = 0; i < 8; i++) {
		i40e_stat_update32(hw, I40E_GLPRT_PXOFFRXC(hw->port, i),
				   pf->stat_offsets_loaded,
				   &osd->priority_xoff_rx[i],
				   &nsd->priority_xoff_rx[i]);
		i40e_stat_update32(hw, I40E_GLPRT_PXONRXC(hw->port, i),
				   pf->stat_offsets_loaded,
				   &osd->priority_xon_rx[i],
@@ -1553,11 +1490,8 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
	}

	ether_addr_copy(netdev->dev_addr, addr->sa_data);
	/* schedule our worker thread which will take care of
	 * applying the new filter changes
	 */
	i40e_service_event_schedule(vsi->back);
	return 0;

	return i40e_sync_vsi_filters(vsi);
}

/**
@@ -1872,8 +1806,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
	bool add_happened = false;
	int filter_list_len = 0;
	u32 changed_flags = 0;
	i40e_status aq_ret = 0;
	bool err_cond = false;
	i40e_status ret = 0;
	int retval = 0;
	struct i40e_pf *pf;
	int num_add = 0;
	int num_del = 0;
@@ -1936,8 +1871,11 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
		}
		spin_unlock_bh(&vsi->mac_filter_list_lock);

		if (err_cond)
		if (err_cond) {
			i40e_cleanup_add_list(&tmp_add_list);
			retval = -ENOMEM;
			goto out;
		}
	}

	/* Now process 'del_list' outside the lock */
@@ -1955,7 +1893,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
			i40e_undo_del_filter_entries(vsi, &tmp_del_list);
			i40e_undo_add_filter_entries(vsi);
			spin_unlock_bh(&vsi->mac_filter_list_lock);
			return -ENOMEM;
			retval = -ENOMEM;
			goto out;
		}

		list_for_each_entry_safe(f, ftmp, &tmp_del_list, list) {
@@ -1973,19 +1912,23 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)

			/* flush a full buffer */
			if (num_del == filter_list_len) {
				ret = i40e_aq_remove_macvlan(&pf->hw,
						  vsi->seid, del_list, num_del,
				aq_ret = i40e_aq_remove_macvlan(&pf->hw,
								vsi->seid,
								del_list,
								num_del,
								NULL);
				aq_err = pf->hw.aq.asq_last_status;
				num_del = 0;
				memset(del_list, 0, sizeof(*del_list));

				if (ret && aq_err != I40E_AQ_RC_ENOENT)
				if (aq_ret && aq_err != I40E_AQ_RC_ENOENT) {
					retval = -EIO;
					dev_err(&pf->pdev->dev,
						"ignoring delete macvlan error, err %s, aq_err %s while flushing a full buffer\n",
						i40e_stat_str(&pf->hw, ret),
						i40e_stat_str(&pf->hw, aq_ret),
						i40e_aq_str(&pf->hw, aq_err));
				}
			}
			/* Release memory for MAC filter entries which were
			 * synced up with HW.
			 */
@@ -1994,15 +1937,16 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
		}

		if (num_del) {
			ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid,
						     del_list, num_del, NULL);
			aq_ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid,
							del_list, num_del,
							NULL);
			aq_err = pf->hw.aq.asq_last_status;
			num_del = 0;

			if (ret && aq_err != I40E_AQ_RC_ENOENT)
			if (aq_ret && aq_err != I40E_AQ_RC_ENOENT)
				dev_info(&pf->pdev->dev,
					 "ignoring delete macvlan error, err %s aq_err %s\n",
					 i40e_stat_str(&pf->hw, ret),
					 i40e_stat_str(&pf->hw, aq_ret),
					 i40e_aq_str(&pf->hw, aq_err));
		}

@@ -2026,7 +1970,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
			spin_lock_bh(&vsi->mac_filter_list_lock);
			i40e_undo_add_filter_entries(vsi);
			spin_unlock_bh(&vsi->mac_filter_list_lock);
			return -ENOMEM;
			retval = -ENOMEM;
			goto out;
		}

		list_for_each_entry_safe(f, ftmp, &tmp_add_list, list) {
@@ -2047,13 +1992,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)

			/* flush a full buffer */
			if (num_add == filter_list_len) {
				ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
				aq_ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
							     add_list, num_add,
							     NULL);
				aq_err = pf->hw.aq.asq_last_status;
				num_add = 0;

				if (ret)
				if (aq_ret)
					break;
				memset(add_list, 0, sizeof(*add_list));
			}
@@ -2065,7 +2010,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
		}

		if (num_add) {
			ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
			aq_ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
						     add_list, num_add, NULL);
			aq_err = pf->hw.aq.asq_last_status;
			num_add = 0;
@@ -2073,10 +2018,11 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
		kfree(add_list);
		add_list = NULL;

		if (add_happened && ret && aq_err != I40E_AQ_RC_EINVAL) {
		if (add_happened && aq_ret && aq_err != I40E_AQ_RC_EINVAL) {
			retval = i40e_aq_rc_to_posix(aq_ret, aq_err);
			dev_info(&pf->pdev->dev,
				 "add filter failed, err %s aq_err %s\n",
				 i40e_stat_str(&pf->hw, ret),
				 i40e_stat_str(&pf->hw, aq_ret),
				 i40e_aq_str(&pf->hw, aq_err));
			if ((pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOSPC) &&
			    !test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
@@ -2094,17 +2040,20 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
		bool cur_multipromisc;

		cur_multipromisc = !!(vsi->current_netdev_flags & IFF_ALLMULTI);
		ret = i40e_aq_set_vsi_multicast_promiscuous(&vsi->back->hw,
		aq_ret = i40e_aq_set_vsi_multicast_promiscuous(&vsi->back->hw,
							       vsi->seid,
							       cur_multipromisc,
							       NULL);
		if (ret)
		if (aq_ret) {
			retval = i40e_aq_rc_to_posix(aq_ret,
						     pf->hw.aq.asq_last_status);
			dev_info(&pf->pdev->dev,
				 "set multi promisc failed, err %s aq_err %s\n",
				 i40e_stat_str(&pf->hw, ret),
				 i40e_stat_str(&pf->hw, aq_ret),
				 i40e_aq_str(&pf->hw,
					     pf->hw.aq.asq_last_status));
		}
	}
	if ((changed_flags & IFF_PROMISC) || promisc_forced_on) {
		bool cur_promisc;

@@ -2122,36 +2071,47 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
				set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
			}
		} else {
			ret = i40e_aq_set_vsi_unicast_promiscuous(
			aq_ret = i40e_aq_set_vsi_unicast_promiscuous(
							  &vsi->back->hw,
							  vsi->seid,
							  cur_promisc, NULL);
			if (ret)
			if (aq_ret) {
				retval =
				i40e_aq_rc_to_posix(aq_ret,
						    pf->hw.aq.asq_last_status);
				dev_info(&pf->pdev->dev,
					 "set unicast promisc failed, err %d, aq_err %d\n",
					 ret, pf->hw.aq.asq_last_status);
			ret = i40e_aq_set_vsi_multicast_promiscuous(
					 aq_ret, pf->hw.aq.asq_last_status);
			}
			aq_ret = i40e_aq_set_vsi_multicast_promiscuous(
							  &vsi->back->hw,
							  vsi->seid,
							  cur_promisc, NULL);
			if (ret)
			if (aq_ret) {
				retval =
				i40e_aq_rc_to_posix(aq_ret,
						    pf->hw.aq.asq_last_status);
				dev_info(&pf->pdev->dev,
					 "set multicast promisc failed, err %d, aq_err %d\n",
					 ret, pf->hw.aq.asq_last_status);
					 aq_ret, pf->hw.aq.asq_last_status);
			}
		}
		ret = i40e_aq_set_vsi_broadcast(&vsi->back->hw,
		aq_ret = i40e_aq_set_vsi_broadcast(&vsi->back->hw,
						   vsi->seid,
						   cur_promisc, NULL);
		if (ret)
		if (aq_ret) {
			retval = i40e_aq_rc_to_posix(aq_ret,
						     pf->hw.aq.asq_last_status);
			dev_info(&pf->pdev->dev,
				 "set brdcast promisc failed, err %s, aq_err %s\n",
				 i40e_stat_str(&pf->hw, ret),
				 i40e_stat_str(&pf->hw, aq_ret),
				 i40e_aq_str(&pf->hw,
					     pf->hw.aq.asq_last_status));
		}

	}
out:
	clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
	return 0;
	return retval;
}

/**
@@ -4368,17 +4328,41 @@ static void i40e_detect_recover_hung_queue(int q_idx, struct i40e_vsi *vsi)
	else
		val = rd32(&pf->hw, I40E_PFINT_DYN_CTL0);

	/* Bail out if interrupts are disabled because napi_poll
	 * execution in-progress or will get scheduled soon.
	 * napi_poll cleans TX and RX queues and updates 'next_to_clean'.
	 */
	if (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK))
		return;

	head = i40e_get_head(tx_ring);

	tx_pending = i40e_get_tx_pending(tx_ring);

	/* Interrupts are disabled and TX pending is non-zero,
	 * trigger the SW interrupt (don't wait). Worst case
	 * there will be one extra interrupt which may result
	 * into not cleaning any queues because queues are cleaned.
	/* HW is done executing descriptors, updated HEAD write back,
	 * but SW hasn't processed those descriptors. If interrupt is
	 * not generated from this point ON, it could result into
	 * dev_watchdog detecting timeout on those netdev_queue,
	 * hence proactively trigger SW interrupt.
	 */
	if (tx_pending && (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK)))
	if (tx_pending) {
		/* NAPI Poll didn't run and clear since it was set */
		if (test_and_clear_bit(I40E_Q_VECTOR_HUNG_DETECT,
				       &tx_ring->q_vector->hung_detected)) {
			netdev_info(vsi->netdev, "VSI_seid %d, Hung TX queue %d, tx_pending: %d, NTC:0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x\n",
				    vsi->seid, q_idx, tx_pending,
				    tx_ring->next_to_clean, head,
				    tx_ring->next_to_use,
				    readl(tx_ring->tail));
			netdev_info(vsi->netdev, "VSI_seid %d, Issuing force_wb for TX queue %d, Interrupt Reg: 0x%x\n",
				    vsi->seid, q_idx, val);
			i40e_force_wb(vsi, tx_ring->q_vector);
		} else {
			/* First Chance - detected possible hung */
			set_bit(I40E_Q_VECTOR_HUNG_DETECT,
				&tx_ring->q_vector->hung_detected);
		}
	}
}

/**
@@ -5310,7 +5294,7 @@ int i40e_open(struct net_device *netdev)
						       TCP_FLAG_CWR) >> 16);
	wr32(&pf->hw, I40E_GLLAN_TSOMSK_L, be32_to_cpu(TCP_FLAG_CWR) >> 16);

#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN)
	vxlan_get_rx_port(netdev);
#endif

@@ -7006,7 +6990,7 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
	i40e_flush(hw);
}

#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN)
/**
 * i40e_sync_vxlan_filters_subtask - Sync the VSI filter list with HW
 * @pf: board private structure
@@ -7073,7 +7057,7 @@ static void i40e_service_task(struct work_struct *work)
	i40e_watchdog_subtask(pf);
	i40e_fdir_reinit_subtask(pf);
	i40e_sync_filters_subtask(pf);
#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN)
	i40e_sync_vxlan_filters_subtask(pf);
#endif
	i40e_clean_adminq_subtask(pf);
@@ -8449,7 +8433,7 @@ static int i40e_set_features(struct net_device *netdev,
	return 0;
}

#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN)
/**
 * i40e_get_vxlan_port_idx - Lookup a possibly offloaded for Rx UDP port
 * @pf: board private structure
@@ -8769,7 +8753,7 @@ static const struct net_device_ops i40e_netdev_ops = {
	.ndo_get_vf_config	= i40e_ndo_get_vf_config,
	.ndo_set_vf_link_state	= i40e_ndo_set_vf_link_state,
	.ndo_set_vf_spoofchk	= i40e_ndo_set_vf_spoofchk,
#ifdef CONFIG_I40E_VXLAN
#if IS_ENABLED(CONFIG_VXLAN)
	.ndo_add_vxlan_port	= i40e_add_vxlan_port,
	.ndo_del_vxlan_port	= i40e_del_vxlan_port,
#endif
+18 −11
Original line number Diff line number Diff line
@@ -235,6 +235,9 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
				 "Filter deleted for PCTYPE %d loc = %d\n",
				 fd_data->pctype, fd_data->fd_id);
	}
	if (err)
		kfree(raw_packet);

	return err ? -EOPNOTSUPP : 0;
}

@@ -312,6 +315,9 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
				 fd_data->pctype, fd_data->fd_id);
	}

	if (err)
		kfree(raw_packet);

	return err ? -EOPNOTSUPP : 0;
}

@@ -322,7 +328,7 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
 * @fd_data: the flow director data required for the FDir descriptor
 * @add: true adds a filter, false removes it
 *
 * Always returns -EOPNOTSUPP
 * Returns 0 if the filters were successfully added or removed
 **/
static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
				    struct i40e_fdir_filter *fd_data,
@@ -387,6 +393,9 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
		}
	}

	if (err)
		kfree(raw_packet);

	return err ? -EOPNOTSUPP : 0;
}

@@ -506,9 +515,6 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
				pf->auto_disable_flags |=
							I40E_FLAG_FD_SB_ENABLED;
			}
		} else {
			dev_info(&pdev->dev,
				"FD filter programming failed due to incorrect filter parameters\n");
		}
	} else if (error == BIT(I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) {
		if (I40E_DEBUG_FD & pf->hw.debug_mask)
@@ -526,11 +532,7 @@ static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring,
					    struct i40e_tx_buffer *tx_buffer)
{
	if (tx_buffer->skb) {
		if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
			kfree(tx_buffer->raw_buf);
		else
		dev_kfree_skb_any(tx_buffer->skb);

		if (dma_unmap_len(tx_buffer, len))
			dma_unmap_single(ring->dev,
					 dma_unmap_addr(tx_buffer, dma),
@@ -542,6 +544,10 @@ static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring,
			       dma_unmap_len(tx_buffer, len),
			       DMA_TO_DEVICE);
	}

	if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
		kfree(tx_buffer->raw_buf);

	tx_buffer->next_to_watch = NULL;
	tx_buffer->skb = NULL;
	dma_unmap_len_set(tx_buffer, len, 0);
@@ -1863,7 +1869,6 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
		q_vector->itr_countdown--;
	else
		q_vector->itr_countdown = ITR_COUNTDOWN_START;

}

/**
@@ -1891,12 +1896,14 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
		return 0;
	}

	/* Clear hung_detected bit */
	clear_bit(I40E_Q_VECTOR_HUNG_DETECT, &q_vector->hung_detected);
	/* Since the actual Tx work is minimal, we can give the Tx a larger
	 * budget and be more aggressive about cleaning up the Tx descriptors.
	 */
	i40e_for_each_ring(ring, q_vector->tx) {
		clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit);
		arm_wb |= ring->arm_wb;
		arm_wb = arm_wb || ring->arm_wb;
		ring->arm_wb = false;
	}

Loading