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

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


Jeff Kirsher says:

====================
10GbE Intel Wired LAN Driver Updates 2016-05-04

This series contains updates to ixgbe, ixgbevf and traffic class helpers.

Sridhar adds helper functions to the tc_mirred header to access tcf_mirred
information and then implements them for ixgbe to enable redirection to
a SRIOV VF or an offloaded MACVLAN device queue via tc 'mirred' action.

Amritha adds support to set filters with multiple header fields (L3,L4)
to match on.

KY Srinivasan from Microsoft add Hyper-V support into ixgbevf.

Emil adds 82599 sub-device IDs that were missing from the list of parts
that support WoL.  Then simplified the logic we use to determine WoL
support by reading the EEPROM bits for MACs X540 and newer.

Preethi cleaned up duplicate and unused device IDs.  Fixed our ethtool
stat reporting where we were ignoring higher 32 bits of stats registers,
so fill out 64 bit stat values into two 32 bit words.

Babu Moger from Oracle improves VF performance issues on SPARC.

Alex Duyck cleans up some of the Hyper-V implementation from KY so that
we can just use function pointers instead of having to identify if a
given VF is running on a Linux or Windows PF.

Usha makes sure that DCB and FCoE is disabled for X550EM_x/a MACs and
cleans up the DCB initialization in the process.

Tony cleans up the API for ixgbevf_update_xcast_mode() so we do not
have to pass in the netdev parameter, since it was never used in the
function.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3e66bab3 8b44a8a0
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -644,6 +644,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE	BIT(24)
#define IXGBE_FLAG_RX_HWTSTAMP_ENABLED		BIT(25)
#define IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER	BIT(26)
#define IXGBE_FLAG_DCB_CAPABLE			BIT(27)

	u32 flags2;
#define IXGBE_FLAG2_RSC_CAPABLE			BIT(0)
@@ -792,7 +793,7 @@ struct ixgbe_adapter {
	unsigned long fwd_bitmask; /* Bitmask indicating in use pools */

#define IXGBE_MAX_LINK_HANDLE 10
	struct ixgbe_mat_field *jump_tables[IXGBE_MAX_LINK_HANDLE];
	struct ixgbe_jump_table *jump_tables[IXGBE_MAX_LINK_HANDLE];
	unsigned long tables;

/* maximum number of RETA entries among all devices supported by ixgbe
@@ -895,7 +896,7 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *, struct ixgbe_ring *);
void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter, struct ixgbe_ring *);
void ixgbe_update_stats(struct ixgbe_adapter *adapter);
int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
bool ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
			 u16 subdevice_id);
#ifdef CONFIG_PCI_IOV
void ixgbe_full_sync_mac_table(struct ixgbe_adapter *adapter);
+12 −15
Original line number Diff line number Diff line
@@ -533,10 +533,8 @@ static void ixgbe_get_regs(struct net_device *netdev,

	/* Flow Control */
	regs_buff[30] = IXGBE_READ_REG(hw, IXGBE_PFCTOP);
	regs_buff[31] = IXGBE_READ_REG(hw, IXGBE_FCTTV(0));
	regs_buff[32] = IXGBE_READ_REG(hw, IXGBE_FCTTV(1));
	regs_buff[33] = IXGBE_READ_REG(hw, IXGBE_FCTTV(2));
	regs_buff[34] = IXGBE_READ_REG(hw, IXGBE_FCTTV(3));
	for (i = 0; i < 4; i++)
		regs_buff[31 + i] = IXGBE_READ_REG(hw, IXGBE_FCTTV(i));
	for (i = 0; i < 8; i++) {
		switch (hw->mac.type) {
		case ixgbe_mac_82598EB:
@@ -720,8 +718,10 @@ static void ixgbe_get_regs(struct net_device *netdev,
	regs_buff[939] = IXGBE_GET_STAT(adapter, bprc);
	regs_buff[940] = IXGBE_GET_STAT(adapter, mprc);
	regs_buff[941] = IXGBE_GET_STAT(adapter, gptc);
	regs_buff[942] = IXGBE_GET_STAT(adapter, gorc);
	regs_buff[944] = IXGBE_GET_STAT(adapter, gotc);
	regs_buff[942] = (u32)IXGBE_GET_STAT(adapter, gorc);
	regs_buff[943] = (u32)(IXGBE_GET_STAT(adapter, gorc) >> 32);
	regs_buff[944] = (u32)IXGBE_GET_STAT(adapter, gotc);
	regs_buff[945] = (u32)(IXGBE_GET_STAT(adapter, gotc) >> 32);
	for (i = 0; i < 8; i++)
		regs_buff[946 + i] = IXGBE_GET_STAT(adapter, rnbc[i]);
	regs_buff[954] = IXGBE_GET_STAT(adapter, ruc);
@@ -731,7 +731,8 @@ static void ixgbe_get_regs(struct net_device *netdev,
	regs_buff[958] = IXGBE_GET_STAT(adapter, mngprc);
	regs_buff[959] = IXGBE_GET_STAT(adapter, mngpdc);
	regs_buff[960] = IXGBE_GET_STAT(adapter, mngptc);
	regs_buff[961] = IXGBE_GET_STAT(adapter, tor);
	regs_buff[961] = (u32)IXGBE_GET_STAT(adapter, tor);
	regs_buff[962] = (u32)(IXGBE_GET_STAT(adapter, tor) >> 32);
	regs_buff[963] = IXGBE_GET_STAT(adapter, tpr);
	regs_buff[964] = IXGBE_GET_STAT(adapter, tpt);
	regs_buff[965] = IXGBE_GET_STAT(adapter, ptc64);
@@ -803,15 +804,11 @@ static void ixgbe_get_regs(struct net_device *netdev,
		regs_buff[1096 + i] = IXGBE_READ_REG(hw, IXGBE_TIC_DW(i));
	regs_buff[1100] = IXGBE_READ_REG(hw, IXGBE_TDPROBE);
	regs_buff[1101] = IXGBE_READ_REG(hw, IXGBE_TXBUFCTRL);
	regs_buff[1102] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA0);
	regs_buff[1103] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA1);
	regs_buff[1104] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA2);
	regs_buff[1105] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA3);
	for (i = 0; i < 4; i++)
		regs_buff[1102 + i] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA(i));
	regs_buff[1106] = IXGBE_READ_REG(hw, IXGBE_RXBUFCTRL);
	regs_buff[1107] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA0);
	regs_buff[1108] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA1);
	regs_buff[1109] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA2);
	regs_buff[1110] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA3);
	for (i = 0; i < 4; i++)
		regs_buff[1107 + i] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA(i));
	for (i = 0; i < 8; i++)
		regs_buff[1111 + i] = IXGBE_READ_REG(hw, IXGBE_PCIE_DIAG(i));
	regs_buff[1119] = IXGBE_READ_REG(hw, IXGBE_RFVAL);
+330 −150
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@
#include <net/vxlan.h>
#include <net/pkt_cls.h>
#include <net/tc_act/tc_gact.h>
#include <net/tc_act/tc_mirred.h>

#include "ixgbe.h"
#include "ixgbe_common.h"
@@ -5558,6 +5559,58 @@ static void ixgbe_tx_timeout(struct net_device *netdev)
	ixgbe_tx_timeout_reset(adapter);
}

#ifdef CONFIG_IXGBE_DCB
static void ixgbe_init_dcb(struct ixgbe_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
	struct tc_configuration *tc;
	int j;

	switch (hw->mac.type) {
	case ixgbe_mac_82598EB:
	case ixgbe_mac_82599EB:
		adapter->dcb_cfg.num_tcs.pg_tcs = MAX_TRAFFIC_CLASS;
		adapter->dcb_cfg.num_tcs.pfc_tcs = MAX_TRAFFIC_CLASS;
		break;
	case ixgbe_mac_X540:
	case ixgbe_mac_X550:
		adapter->dcb_cfg.num_tcs.pg_tcs = X540_TRAFFIC_CLASS;
		adapter->dcb_cfg.num_tcs.pfc_tcs = X540_TRAFFIC_CLASS;
		break;
	case ixgbe_mac_X550EM_x:
	case ixgbe_mac_x550em_a:
	default:
		adapter->dcb_cfg.num_tcs.pg_tcs = DEF_TRAFFIC_CLASS;
		adapter->dcb_cfg.num_tcs.pfc_tcs = DEF_TRAFFIC_CLASS;
		break;
	}

	/* Configure DCB traffic classes */
	for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
		tc = &adapter->dcb_cfg.tc_config[j];
		tc->path[DCB_TX_CONFIG].bwg_id = 0;
		tc->path[DCB_TX_CONFIG].bwg_percent = 12 + (j & 1);
		tc->path[DCB_RX_CONFIG].bwg_id = 0;
		tc->path[DCB_RX_CONFIG].bwg_percent = 12 + (j & 1);
		tc->dcb_pfc = pfc_disabled;
	}

	/* Initialize default user to priority mapping, UPx->TC0 */
	tc = &adapter->dcb_cfg.tc_config[0];
	tc->path[DCB_TX_CONFIG].up_to_tc_bitmap = 0xFF;
	tc->path[DCB_RX_CONFIG].up_to_tc_bitmap = 0xFF;

	adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
	adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
	adapter->dcb_cfg.pfc_mode_enable = false;
	adapter->dcb_set_bitmap = 0x00;
	if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE)
		adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
	memcpy(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
	       sizeof(adapter->temp_dcb_cfg));
}
#endif

/**
 * ixgbe_sw_init - Initialize general software structures (struct ixgbe_adapter)
 * @adapter: board private structure to initialize
@@ -5573,10 +5626,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
	unsigned int rss, fdir;
	u32 fwsm;
	u16 device_caps;
#ifdef CONFIG_IXGBE_DCB
	int j;
	struct tc_configuration *tc;
#endif
	int i;

	/* PCI config space info */

@@ -5598,6 +5648,10 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
#ifdef CONFIG_IXGBE_DCA
	adapter->flags |= IXGBE_FLAG_DCA_CAPABLE;
#endif
#ifdef CONFIG_IXGBE_DCB
	adapter->flags |= IXGBE_FLAG_DCB_CAPABLE;
	adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
#endif
#ifdef IXGBE_FCOE
	adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
	adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
@@ -5608,7 +5662,14 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
#endif /* IXGBE_FCOE */

	/* initialize static ixgbe jump table entries */
	adapter->jump_tables[0] = ixgbe_ipv4_fields;
	adapter->jump_tables[0] = kzalloc(sizeof(*adapter->jump_tables[0]),
					  GFP_KERNEL);
	if (!adapter->jump_tables[0])
		return -ENOMEM;
	adapter->jump_tables[0]->mat = ixgbe_ipv4_fields;

	for (i = 1; i < IXGBE_MAX_LINK_HANDLE; i++)
		adapter->jump_tables[i] = NULL;

	adapter->mac_table = kzalloc(sizeof(struct ixgbe_mac_addr) *
				     hw->mac.num_rar_entries,
@@ -5647,6 +5708,16 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
		break;
	case ixgbe_mac_X550EM_x:
	case ixgbe_mac_x550em_a:
#ifdef CONFIG_IXGBE_DCB
		adapter->flags &= ~IXGBE_FLAG_DCB_CAPABLE;
#endif
#ifdef IXGBE_FCOE
		adapter->flags &= ~IXGBE_FLAG_FCOE_CAPABLE;
#ifdef CONFIG_IXGBE_DCB
		adapter->fcoe.up = 0;
#endif /* IXGBE_DCB */
#endif /* IXGBE_FCOE */
	/* Fall Through */
	case ixgbe_mac_X550:
#ifdef CONFIG_IXGBE_DCA
		adapter->flags &= ~IXGBE_FLAG_DCA_CAPABLE;
@@ -5668,43 +5739,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
	spin_lock_init(&adapter->fdir_perfect_lock);

#ifdef CONFIG_IXGBE_DCB
	switch (hw->mac.type) {
	case ixgbe_mac_X540:
	case ixgbe_mac_X550:
	case ixgbe_mac_X550EM_x:
	case ixgbe_mac_x550em_a:
		adapter->dcb_cfg.num_tcs.pg_tcs = X540_TRAFFIC_CLASS;
		adapter->dcb_cfg.num_tcs.pfc_tcs = X540_TRAFFIC_CLASS;
		break;
	default:
		adapter->dcb_cfg.num_tcs.pg_tcs = MAX_TRAFFIC_CLASS;
		adapter->dcb_cfg.num_tcs.pfc_tcs = MAX_TRAFFIC_CLASS;
		break;
	}

	/* Configure DCB traffic classes */
	for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
		tc = &adapter->dcb_cfg.tc_config[j];
		tc->path[DCB_TX_CONFIG].bwg_id = 0;
		tc->path[DCB_TX_CONFIG].bwg_percent = 12 + (j & 1);
		tc->path[DCB_RX_CONFIG].bwg_id = 0;
		tc->path[DCB_RX_CONFIG].bwg_percent = 12 + (j & 1);
		tc->dcb_pfc = pfc_disabled;
	}

	/* Initialize default user to priority mapping, UPx->TC0 */
	tc = &adapter->dcb_cfg.tc_config[0];
	tc->path[DCB_TX_CONFIG].up_to_tc_bitmap = 0xFF;
	tc->path[DCB_RX_CONFIG].up_to_tc_bitmap = 0xFF;

	adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
	adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
	adapter->dcb_cfg.pfc_mode_enable = false;
	adapter->dcb_set_bitmap = 0x00;
	adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
	memcpy(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
	       sizeof(adapter->temp_dcb_cfg));

	ixgbe_init_dcb(adapter);
#endif

	/* default flow control settings */
@@ -8319,6 +8354,134 @@ static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter,
	return 0;
}

#ifdef CONFIG_NET_CLS_ACT
static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
				  u8 *queue, u64 *action)
{
	unsigned int num_vfs = adapter->num_vfs, vf;
	struct net_device *upper;
	struct list_head *iter;

	/* redirect to a SRIOV VF */
	for (vf = 0; vf < num_vfs; ++vf) {
		upper = pci_get_drvdata(adapter->vfinfo[vf].vfdev);
		if (upper->ifindex == ifindex) {
			if (adapter->num_rx_pools > 1)
				*queue = vf * 2;
			else
				*queue = vf * adapter->num_rx_queues_per_pool;

			*action = vf + 1;
			*action <<= ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF;
			return 0;
		}
	}

	/* redirect to a offloaded macvlan netdev */
	netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
		if (netif_is_macvlan(upper)) {
			struct macvlan_dev *dfwd = netdev_priv(upper);
			struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;

			if (vadapter && vadapter->netdev->ifindex == ifindex) {
				*queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
				*action = *queue;
				return 0;
			}
		}
	}

	return -EINVAL;
}

static int parse_tc_actions(struct ixgbe_adapter *adapter,
			    struct tcf_exts *exts, u64 *action, u8 *queue)
{
	const struct tc_action *a;
	int err;

	if (tc_no_actions(exts))
		return -EINVAL;

	tc_for_each_action(a, exts) {

		/* Drop action */
		if (is_tcf_gact_shot(a)) {
			*action = IXGBE_FDIR_DROP_QUEUE;
			*queue = IXGBE_FDIR_DROP_QUEUE;
			return 0;
		}

		/* Redirect to a VF or a offloaded macvlan */
		if (is_tcf_mirred_redirect(a)) {
			int ifindex = tcf_mirred_ifindex(a);

			err = handle_redirect_action(adapter, ifindex, queue,
						     action);
			if (err == 0)
				return err;
		}
	}

	return -EINVAL;
}
#else
static int parse_tc_actions(struct ixgbe_adapter *adapter,
			    struct tcf_exts *exts, u64 *action, u8 *queue)
{
	return -EINVAL;
}
#endif /* CONFIG_NET_CLS_ACT */

static int ixgbe_clsu32_build_input(struct ixgbe_fdir_filter *input,
				    union ixgbe_atr_input *mask,
				    struct tc_cls_u32_offload *cls,
				    struct ixgbe_mat_field *field_ptr,
				    struct ixgbe_nexthdr *nexthdr)
{
	int i, j, off;
	__be32 val, m;
	bool found_entry = false, found_jump_field = false;

	for (i = 0; i < cls->knode.sel->nkeys; i++) {
		off = cls->knode.sel->keys[i].off;
		val = cls->knode.sel->keys[i].val;
		m = cls->knode.sel->keys[i].mask;

		for (j = 0; field_ptr[j].val; j++) {
			if (field_ptr[j].off == off) {
				field_ptr[j].val(input, mask, val, m);
				input->filter.formatted.flow_type |=
					field_ptr[j].type;
				found_entry = true;
				break;
			}
		}
		if (nexthdr) {
			if (nexthdr->off == cls->knode.sel->keys[i].off &&
			    nexthdr->val == cls->knode.sel->keys[i].val &&
			    nexthdr->mask == cls->knode.sel->keys[i].mask)
				found_jump_field = true;
			else
				continue;
		}
	}

	if (nexthdr && !found_jump_field)
		return -EINVAL;

	if (!found_entry)
		return 0;

	mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
				    IXGBE_ATR_L4TYPE_MASK;

	if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4)
		mask->formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK;

	return 0;
}

static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
				  __be16 protocol,
				  struct tc_cls_u32_offload *cls)
@@ -8326,16 +8489,13 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
	u32 loc = cls->knode.handle & 0xfffff;
	struct ixgbe_hw *hw = &adapter->hw;
	struct ixgbe_mat_field *field_ptr;
	struct ixgbe_fdir_filter *input;
	union ixgbe_atr_input mask;
#ifdef CONFIG_NET_CLS_ACT
	const struct tc_action *a;
#endif
	int i, err = 0;
	struct ixgbe_fdir_filter *input = NULL;
	union ixgbe_atr_input *mask = NULL;
	struct ixgbe_jump_table *jump = NULL;
	int i, err = -EINVAL;
	u8 queue;
	u32 uhtid, link_uhtid;

	memset(&mask, 0, sizeof(union ixgbe_atr_input));
	uhtid = TC_U32_USERHTID(cls->knode.handle);
	link_uhtid = TC_U32_USERHTID(cls->knode.link_handle);

@@ -8347,39 +8507,11 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
	 * headers when needed.
	 */
	if (protocol != htons(ETH_P_IP))
		return -EINVAL;

	if (link_uhtid) {
		struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps;

		if (link_uhtid >= IXGBE_MAX_LINK_HANDLE)
			return -EINVAL;

		if (!test_bit(link_uhtid - 1, &adapter->tables))
			return -EINVAL;

		for (i = 0; nexthdr[i].jump; i++) {
			if (nexthdr[i].o != cls->knode.sel->offoff ||
			    nexthdr[i].s != cls->knode.sel->offshift ||
			    nexthdr[i].m != cls->knode.sel->offmask ||
			    /* do not support multiple key jumps its just mad */
			    cls->knode.sel->nkeys > 1)
				return -EINVAL;

			if (nexthdr[i].off == cls->knode.sel->keys[0].off &&
			    nexthdr[i].val == cls->knode.sel->keys[0].val &&
			    nexthdr[i].mask == cls->knode.sel->keys[0].mask) {
				adapter->jump_tables[link_uhtid] =
								nexthdr[i].jump;
				break;
			}
		}
		return 0;
	}
		return err;

	if (loc >= ((1024 << adapter->fdir_pballoc) - 2)) {
		e_err(drv, "Location out of range\n");
		return -EINVAL;
		return err;
	}

	/* cls u32 is a graph starting at root node 0x800. The driver tracks
@@ -8390,87 +8522,123 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
	 * this function _should_ be generic try not to hardcode values here.
	 */
	if (uhtid == 0x800) {
		field_ptr = adapter->jump_tables[0];
		field_ptr = (adapter->jump_tables[0])->mat;
	} else {
		if (uhtid >= IXGBE_MAX_LINK_HANDLE)
			return -EINVAL;

		field_ptr = adapter->jump_tables[uhtid];
			return err;
		if (!adapter->jump_tables[uhtid])
			return err;
		field_ptr = (adapter->jump_tables[uhtid])->mat;
	}

	if (!field_ptr)
		return -EINVAL;
		return err;

	input = kzalloc(sizeof(*input), GFP_KERNEL);
	if (!input)
		return -ENOMEM;
	/* At this point we know the field_ptr is valid and need to either
	 * build cls_u32 link or attach filter. Because adding a link to
	 * a handle that does not exist is invalid and the same for adding
	 * rules to handles that don't exist.
	 */

	for (i = 0; i < cls->knode.sel->nkeys; i++) {
		int off = cls->knode.sel->keys[i].off;
		__be32 val = cls->knode.sel->keys[i].val;
		__be32 m = cls->knode.sel->keys[i].mask;
		bool found_entry = false;
		int j;
	if (link_uhtid) {
		struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps;

		for (j = 0; field_ptr[j].val; j++) {
			if (field_ptr[j].off == off) {
				field_ptr[j].val(input, &mask, val, m);
				input->filter.formatted.flow_type |=
					field_ptr[j].type;
				found_entry = true;
		if (link_uhtid >= IXGBE_MAX_LINK_HANDLE)
			return err;

		if (!test_bit(link_uhtid - 1, &adapter->tables))
			return err;

		for (i = 0; nexthdr[i].jump; i++) {
			if (nexthdr[i].o != cls->knode.sel->offoff ||
			    nexthdr[i].s != cls->knode.sel->offshift ||
			    nexthdr[i].m != cls->knode.sel->offmask)
				return err;

			jump = kzalloc(sizeof(*jump), GFP_KERNEL);
			if (!jump)
				return -ENOMEM;
			input = kzalloc(sizeof(*input), GFP_KERNEL);
			if (!input) {
				err = -ENOMEM;
				goto free_jump;
			}
			mask = kzalloc(sizeof(*mask), GFP_KERNEL);
			if (!mask) {
				err = -ENOMEM;
				goto free_input;
			}
			jump->input = input;
			jump->mask = mask;
			err = ixgbe_clsu32_build_input(input, mask, cls,
						       field_ptr, &nexthdr[i]);
			if (!err) {
				jump->mat = nexthdr[i].jump;
				adapter->jump_tables[link_uhtid] = jump;
				break;
			}
		}

		if (!found_entry)
			goto err_out;
		return 0;
	}

	mask.formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
				   IXGBE_ATR_L4TYPE_MASK;

	if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4)
		mask.formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK;
	input = kzalloc(sizeof(*input), GFP_KERNEL);
	if (!input)
		return -ENOMEM;
	mask = kzalloc(sizeof(*mask), GFP_KERNEL);
	if (!mask) {
		err = -ENOMEM;
		goto free_input;
	}

#ifdef CONFIG_NET_CLS_ACT
	if (list_empty(&cls->knode.exts->actions))
	if ((uhtid != 0x800) && (adapter->jump_tables[uhtid])) {
		if ((adapter->jump_tables[uhtid])->input)
			memcpy(input, (adapter->jump_tables[uhtid])->input,
			       sizeof(*input));
		if ((adapter->jump_tables[uhtid])->mask)
			memcpy(mask, (adapter->jump_tables[uhtid])->mask,
			       sizeof(*mask));
	}
	err = ixgbe_clsu32_build_input(input, mask, cls, field_ptr, NULL);
	if (err)
		goto err_out;

	list_for_each_entry(a, &cls->knode.exts->actions, list) {
		if (!is_tcf_gact_shot(a))
	err = parse_tc_actions(adapter, cls->knode.exts, &input->action,
			       &queue);
	if (err < 0)
		goto err_out;
	}
#endif

	input->action = IXGBE_FDIR_DROP_QUEUE;
	queue = IXGBE_FDIR_DROP_QUEUE;
	input->sw_idx = loc;

	spin_lock(&adapter->fdir_perfect_lock);

	if (hlist_empty(&adapter->fdir_filter_list)) {
		memcpy(&adapter->fdir_mask, &mask, sizeof(mask));
		err = ixgbe_fdir_set_input_mask_82599(hw, &mask);
		memcpy(&adapter->fdir_mask, mask, sizeof(*mask));
		err = ixgbe_fdir_set_input_mask_82599(hw, mask);
		if (err)
			goto err_out_w_lock;
	} else if (memcmp(&adapter->fdir_mask, &mask, sizeof(mask))) {
	} else if (memcmp(&adapter->fdir_mask, mask, sizeof(*mask))) {
		err = -EINVAL;
		goto err_out_w_lock;
	}

	ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask);
	ixgbe_atr_compute_perfect_hash_82599(&input->filter, mask);
	err = ixgbe_fdir_write_perfect_filter_82599(hw, &input->filter,
						    input->sw_idx, queue);
	if (!err)
		ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
	spin_unlock(&adapter->fdir_perfect_lock);

	kfree(mask);
	return err;
err_out_w_lock:
	spin_unlock(&adapter->fdir_perfect_lock);
err_out:
	kfree(mask);
free_input:
	kfree(input);
	return -EINVAL;
free_jump:
	kfree(jump);
	return err;
}

static int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
@@ -9043,7 +9211,7 @@ static inline int ixgbe_enumerate_functions(struct ixgbe_adapter *adapter)

/**
 * ixgbe_wol_supported - Check whether device supports WoL
 * @hw: hw specific details
 * @adapter: the adapter private structure
 * @device_id: the device ID
 * @subdev_id: the subsystem device ID
 *
@@ -9051,19 +9219,33 @@ static inline int ixgbe_enumerate_functions(struct ixgbe_adapter *adapter)
 * which devices have WoL support
 *
 **/
int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
bool ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
			 u16 subdevice_id)
{
	struct ixgbe_hw *hw = &adapter->hw;
	u16 wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK;
	int is_wol_supported = 0;

	/* WOL not supported on 82598 */
	if (hw->mac.type == ixgbe_mac_82598EB)
		return false;

	/* check eeprom to see if WOL is enabled for X540 and newer */
	if (hw->mac.type >= ixgbe_mac_X540) {
		if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
		    ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
		     (hw->bus.func == 0)))
			return true;
	}

	/* WOL is determined based on device IDs for 82599 MACs */
	switch (device_id) {
	case IXGBE_DEV_ID_82599_SFP:
		/* Only these subdevices could supports WOL */
		switch (subdevice_id) {
		case IXGBE_SUBDEV_ID_82599_SFP_WOL0:
		case IXGBE_SUBDEV_ID_82599_560FLR:
		case IXGBE_SUBDEV_ID_82599_LOM_SNAP6:
		case IXGBE_SUBDEV_ID_82599_SFP_WOL0:
		case IXGBE_SUBDEV_ID_82599_SFP_2OCP:
			/* only support first port */
			if (hw->bus.func != 0)
				break;
@@ -9071,44 +9253,31 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
		case IXGBE_SUBDEV_ID_82599_SFP:
		case IXGBE_SUBDEV_ID_82599_RNDC:
		case IXGBE_SUBDEV_ID_82599_ECNA_DP:
		case IXGBE_SUBDEV_ID_82599_LOM_SFP:
			is_wol_supported = 1;
			break;
		case IXGBE_SUBDEV_ID_82599_SFP_1OCP:
		case IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM1:
		case IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM2:
			return true;
		}
		break;
	case IXGBE_DEV_ID_82599EN_SFP:
		/* Only this subdevice supports WOL */
		/* Only these subdevices support WOL */
		switch (subdevice_id) {
		case IXGBE_SUBDEV_ID_82599EN_SFP_OCP1:
			is_wol_supported = 1;
			break;
			return true;
		}
		break;
	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
		/* All except this subdevice support WOL */
		if (subdevice_id != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ)
			is_wol_supported = 1;
			return true;
		break;
	case IXGBE_DEV_ID_82599_KX4:
		is_wol_supported = 1;
		break;
	case IXGBE_DEV_ID_X540T:
	case IXGBE_DEV_ID_X540T1:
	case IXGBE_DEV_ID_X550T:
	case IXGBE_DEV_ID_X550T1:
	case IXGBE_DEV_ID_X550EM_X_KX4:
	case IXGBE_DEV_ID_X550EM_X_KR:
	case IXGBE_DEV_ID_X550EM_X_10G_T:
		/* check eeprom to see if enabled wol */
		if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
		    ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
		     (hw->bus.func == 0))) {
			is_wol_supported = 1;
		}
		return  true;
	default:
		break;
	}

	return is_wol_supported;
	return false;
}

/**
@@ -9352,6 +9521,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	netdev->priv_flags |= IFF_SUPP_NOFCS;

#ifdef CONFIG_IXGBE_DCB
	if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE)
		netdev->dcbnl_ops = &dcbnl_ops;
#endif

@@ -9542,6 +9712,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	ixgbe_disable_sriov(adapter);
	adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP;
	iounmap(adapter->io_addr);
	kfree(adapter->jump_tables[0]);
	kfree(adapter->mac_table);
err_ioremap:
	disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
@@ -9570,6 +9741,7 @@ static void ixgbe_remove(struct pci_dev *pdev)
	struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
	struct net_device *netdev;
	bool disable_dev;
	int i;

	/* if !adapter then we already cleaned up in probe */
	if (!adapter)
@@ -9619,6 +9791,14 @@ static void ixgbe_remove(struct pci_dev *pdev)

	e_dev_info("complete\n");

	for (i = 0; i < IXGBE_MAX_LINK_HANDLE; i++) {
		if (adapter->jump_tables[i]) {
			kfree(adapter->jump_tables[i]->input);
			kfree(adapter->jump_tables[i]->mask);
		}
		kfree(adapter->jump_tables[i]);
	}

	kfree(adapter->mac_table);
	disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
	free_netdev(netdev);
+6 −0
Original line number Diff line number Diff line
@@ -38,6 +38,12 @@ struct ixgbe_mat_field {
	unsigned int type;
};

struct ixgbe_jump_table {
	struct ixgbe_mat_field *mat;
	struct ixgbe_fdir_filter *input;
	union ixgbe_atr_input *mask;
};

static inline int ixgbe_mat_prgm_sip(struct ixgbe_fdir_filter *input,
				     union ixgbe_atr_input *mask,
				     u32 val, u32 m)
+10 −15
Original line number Diff line number Diff line
@@ -59,8 +59,12 @@
#define IXGBE_SUBDEV_ID_82599_RNDC       0x1F72
#define IXGBE_SUBDEV_ID_82599_560FLR     0x17D0
#define IXGBE_SUBDEV_ID_82599_SP_560FLR  0x211B
#define IXGBE_SUBDEV_ID_82599_LOM_SNAP6		0x2159
#define IXGBE_SUBDEV_ID_82599_SFP_1OCP		0x000D
#define IXGBE_SUBDEV_ID_82599_SFP_2OCP		0x0008
#define IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM1	0x8976
#define IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM2	0x06EE
#define IXGBE_SUBDEV_ID_82599_ECNA_DP    0x0470
#define IXGBE_SUBDEV_ID_82599_LOM_SFP    0x8976
#define IXGBE_DEV_ID_82599_SFP_EM        0x1507
#define IXGBE_DEV_ID_82599_SFP_SF2       0x154D
#define IXGBE_DEV_ID_82599EN_SFP         0x1557
@@ -89,10 +93,6 @@
#define IXGBE_DEV_ID_X550EM_A_SFP	0x15CE

/* VF Device IDs */
#define IXGBE_DEV_ID_X550_VF_HV	0x1564
#define IXGBE_DEV_ID_X550_VF		0x1565
#define IXGBE_DEV_ID_X550EM_X_VF	0x15A8
#define IXGBE_DEV_ID_X550EM_X_VF_HV	0x15A9
#define IXGBE_DEV_ID_82599_VF		0x10ED
#define IXGBE_DEV_ID_X540_VF		0x1515
#define IXGBE_DEV_ID_X550_VF		0x1565
@@ -548,6 +548,7 @@ struct ixgbe_thermal_sensor_data {
/* DCB registers */
#define MAX_TRAFFIC_CLASS        8
#define X540_TRAFFIC_CLASS       4
#define DEF_TRAFFIC_CLASS        1
#define IXGBE_RMCS      0x03D00
#define IXGBE_DPMCS     0x07F40
#define IXGBE_PDPMCS    0x0CD00
@@ -1060,15 +1061,9 @@ struct ixgbe_thermal_sensor_data {
#define IXGBE_TIC_DW2(_i) (0x082B0 + ((_i) * 4))
#define IXGBE_TDPROBE     0x07F20
#define IXGBE_TXBUFCTRL   0x0C600
#define IXGBE_TXBUFDATA0  0x0C610
#define IXGBE_TXBUFDATA1  0x0C614
#define IXGBE_TXBUFDATA2  0x0C618
#define IXGBE_TXBUFDATA3  0x0C61C
#define IXGBE_TXBUFDATA(_i) (0x0C610 + ((_i) * 4)) /* 4 of these (0-3) */
#define IXGBE_RXBUFCTRL   0x03600
#define IXGBE_RXBUFDATA0  0x03610
#define IXGBE_RXBUFDATA1  0x03614
#define IXGBE_RXBUFDATA2  0x03618
#define IXGBE_RXBUFDATA3  0x0361C
#define IXGBE_RXBUFDATA(_i) (0x03610 + ((_i) * 4)) /* 4 of these (0-3) */
#define IXGBE_PCIE_DIAG(_i)     (0x11090 + ((_i) * 4)) /* 8 of these */
#define IXGBE_RFVAL     0x050A4
#define IXGBE_MDFTC1    0x042B8
Loading