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

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


Jeff Kirsher says:

====================
40GbE Intel Wired LAN Driver Updates 2016-02-17

This series contains updates to i40e/i40evf only.

Jesse cleans up a duplicate declaration in probe.  Then fixes a bug where the
driver was using a offset based off a DMA handle while mapping and unmapping
using sync_single_range_for_[cpu|device], when it should be using DMA handle
(returned from alloc_coherent) and the offset of the memory to be sync'd.
Fixed an issue where sync_vsi_filter() was allocating memory in a way that
could sleep (GFP_KERNEL) which was causing a problem when called by the
team driver under rcu_read_lock().

Shannon adds a check to ensure we do not attempt to do TSO when
skb->ip_summed is not set to CHECKSUM_PARTIAL.

Kiran add functions related to port mirroring features such as add/delete
mirror rule.

Jacob assigns the i40e_pf structure directly instead of using a large
memcpy, to avoid a sparse warning and lets the compiler optimize the copy
since it know the size of the structure in advance.

Anjali enables GENEVE capability for XL710/X710 devices with firmware API
version higher than 1.4.  Added flag for automatic rule eviction feature
for X722, which is disabled by default.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 024af151 ba94272d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@
#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_PRIV_FLAGS_HW_ATR_EVICT	BIT(5)

#define I40E_NVM_VERSION_LO_SHIFT  0
#define I40E_NVM_VERSION_LO_MASK   (0xff << I40E_NVM_VERSION_LO_SHIFT)
@@ -757,7 +758,6 @@ static inline void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector)
	/* skip the flush */
}

void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector);
void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf);
void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf);
#ifdef I40E_FCOE
+162 −0
Original line number Diff line number Diff line
@@ -2032,6 +2032,37 @@ i40e_status i40e_aq_set_vsi_broadcast(struct i40e_hw *hw,
	return status;
}

/**
 * i40e_aq_set_vsi_vlan_promisc - control the VLAN promiscuous setting
 * @hw: pointer to the hw struct
 * @seid: vsi number
 * @enable: set MAC L2 layer unicast promiscuous enable/disable for a given VLAN
 * @cmd_details: pointer to command details structure or NULL
 **/
i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,
				       u16 seid, bool enable,
				       struct i40e_asq_cmd_details *cmd_details)
{
	struct i40e_aq_desc desc;
	struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
		(struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw;
	i40e_status status;
	u16 flags = 0;

	i40e_fill_default_direct_cmd_desc(&desc,
					i40e_aqc_opc_set_vsi_promiscuous_modes);
	if (enable)
		flags |= I40E_AQC_SET_VSI_PROMISC_VLAN;

	cmd->promiscuous_flags = cpu_to_le16(flags);
	cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_VLAN);
	cmd->seid = cpu_to_le16(seid);

	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);

	return status;
}

/**
 * i40e_get_vsi_params - get VSI configuration info
 * @hw: pointer to the hw struct
@@ -2469,6 +2500,137 @@ i40e_status i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 seid,
	return status;
}

/**
 * i40e_mirrorrule_op - Internal helper function to add/delete mirror rule
 * @hw: pointer to the hw struct
 * @opcode: AQ opcode for add or delete mirror rule
 * @sw_seid: Switch SEID (to which rule refers)
 * @rule_type: Rule Type (ingress/egress/VLAN)
 * @id: Destination VSI SEID or Rule ID
 * @count: length of the list
 * @mr_list: list of mirrored VSI SEIDs or VLAN IDs
 * @cmd_details: pointer to command details structure or NULL
 * @rule_id: Rule ID returned from FW
 * @rule_used: Number of rules used in internal switch
 * @rule_free: Number of rules free in internal switch
 *
 * Add/Delete a mirror rule to a specific switch. Mirror rules are supported for
 * VEBs/VEPA elements only
 **/
static i40e_status i40e_mirrorrule_op(struct i40e_hw *hw,
				u16 opcode, u16 sw_seid, u16 rule_type, u16 id,
				u16 count, __le16 *mr_list,
				struct i40e_asq_cmd_details *cmd_details,
				u16 *rule_id, u16 *rules_used, u16 *rules_free)
{
	struct i40e_aq_desc desc;
	struct i40e_aqc_add_delete_mirror_rule *cmd =
		(struct i40e_aqc_add_delete_mirror_rule *)&desc.params.raw;
	struct i40e_aqc_add_delete_mirror_rule_completion *resp =
	(struct i40e_aqc_add_delete_mirror_rule_completion *)&desc.params.raw;
	i40e_status status;
	u16 buf_size;

	buf_size = count * sizeof(*mr_list);

	/* prep the rest of the request */
	i40e_fill_default_direct_cmd_desc(&desc, opcode);
	cmd->seid = cpu_to_le16(sw_seid);
	cmd->rule_type = cpu_to_le16(rule_type &
				     I40E_AQC_MIRROR_RULE_TYPE_MASK);
	cmd->num_entries = cpu_to_le16(count);
	/* Dest VSI for add, rule_id for delete */
	cmd->destination = cpu_to_le16(id);
	if (mr_list) {
		desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF |
						I40E_AQ_FLAG_RD));
		if (buf_size > I40E_AQ_LARGE_BUF)
			desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
	}

	status = i40e_asq_send_command(hw, &desc, mr_list, buf_size,
				       cmd_details);
	if (!status ||
	    hw->aq.asq_last_status == I40E_AQ_RC_ENOSPC) {
		if (rule_id)
			*rule_id = le16_to_cpu(resp->rule_id);
		if (rules_used)
			*rules_used = le16_to_cpu(resp->mirror_rules_used);
		if (rules_free)
			*rules_free = le16_to_cpu(resp->mirror_rules_free);
	}
	return status;
}

/**
 * i40e_aq_add_mirrorrule - add a mirror rule
 * @hw: pointer to the hw struct
 * @sw_seid: Switch SEID (to which rule refers)
 * @rule_type: Rule Type (ingress/egress/VLAN)
 * @dest_vsi: SEID of VSI to which packets will be mirrored
 * @count: length of the list
 * @mr_list: list of mirrored VSI SEIDs or VLAN IDs
 * @cmd_details: pointer to command details structure or NULL
 * @rule_id: Rule ID returned from FW
 * @rule_used: Number of rules used in internal switch
 * @rule_free: Number of rules free in internal switch
 *
 * Add mirror rule. Mirror rules are supported for VEBs or VEPA elements only
 **/
i40e_status i40e_aq_add_mirrorrule(struct i40e_hw *hw, u16 sw_seid,
			u16 rule_type, u16 dest_vsi, u16 count, __le16 *mr_list,
			struct i40e_asq_cmd_details *cmd_details,
			u16 *rule_id, u16 *rules_used, u16 *rules_free)
{
	if (!(rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS ||
	    rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS)) {
		if (count == 0 || !mr_list)
			return I40E_ERR_PARAM;
	}

	return i40e_mirrorrule_op(hw, i40e_aqc_opc_add_mirror_rule, sw_seid,
				  rule_type, dest_vsi, count, mr_list,
				  cmd_details, rule_id, rules_used, rules_free);
}

/**
 * i40e_aq_delete_mirrorrule - delete a mirror rule
 * @hw: pointer to the hw struct
 * @sw_seid: Switch SEID (to which rule refers)
 * @rule_type: Rule Type (ingress/egress/VLAN)
 * @count: length of the list
 * @rule_id: Rule ID that is returned in the receive desc as part of
 *		add_mirrorrule.
 * @mr_list: list of mirrored VLAN IDs to be removed
 * @cmd_details: pointer to command details structure or NULL
 * @rule_used: Number of rules used in internal switch
 * @rule_free: Number of rules free in internal switch
 *
 * Delete a mirror rule. Mirror rules are supported for VEBs/VEPA elements only
 **/
i40e_status i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid,
			u16 rule_type, u16 rule_id, u16 count, __le16 *mr_list,
			struct i40e_asq_cmd_details *cmd_details,
			u16 *rules_used, u16 *rules_free)
{
	/* Rule ID has to be valid except rule_type: INGRESS VLAN mirroring */
	if (rule_type != I40E_AQC_MIRROR_RULE_TYPE_VLAN) {
		if (!rule_id)
			return I40E_ERR_PARAM;
	} else {
		/* count and mr_list shall be valid for rule_type INGRESS VLAN
		 * mirroring. For other rule_type, count and rule_type should
		 * not matter.
		 */
		if (count == 0 || !mr_list)
			return I40E_ERR_PARAM;
	}

	return i40e_mirrorrule_op(hw, i40e_aqc_opc_delete_mirror_rule, sw_seid,
				  rule_type, rule_id, count, mr_list,
				  cmd_details, NULL, rules_used, rules_free);
}

/**
 * i40e_aq_send_msg_to_vf
 * @hw: pointer to the hardware structure
+5 −3
Original line number Diff line number Diff line
@@ -185,9 +185,11 @@ static ssize_t i40e_dbg_dump_write(struct file *filp,
		if (i40e_dbg_prep_dump_buf(pf, buflen)) {
			p = i40e_dbg_dump_buf;

			len = sizeof(struct i40e_pf);
			memcpy(p, pf, len);
			p += len;
			/* avoid use of memcpy here due to sparse warning
			 * about copy size.
			 */
			*((struct i40e_pf *)p) = *pf;
			p += sizeof(struct i40e_pf);

			len = (sizeof(struct i40e_aq_desc)
					* pf->hw.aq.num_asq_entries);
+11 −0
Original line number Diff line number Diff line
@@ -89,6 +89,8 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {
	I40E_VSI_STAT("rx_unknown_protocol", eth_stats.rx_unknown_protocol),
	I40E_VSI_STAT("tx_linearize", tx_linearize),
	I40E_VSI_STAT("tx_force_wb", tx_force_wb),
	I40E_VSI_STAT("rx_alloc_fail", rx_buf_failed),
	I40E_VSI_STAT("rx_pg_alloc_fail", rx_page_failed),
};

/* These PF_STATs might look like duplicates of some NETDEV_STATs,
@@ -233,6 +235,7 @@ static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
	"flow-director-atr",
	"veb-stats",
	"packet-split",
	"hw-atr-eviction",
};

#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings)
@@ -2729,6 +2732,8 @@ static u32 i40e_get_priv_flags(struct net_device *dev)
		I40E_PRIV_FLAGS_VEB_STATS : 0;
	ret_flags |= pf->flags & I40E_FLAG_RX_PS_ENABLED ?
		I40E_PRIV_FLAGS_PS : 0;
	ret_flags |= pf->auto_disable_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE ?
		0 : I40E_PRIV_FLAGS_HW_ATR_EVICT;

	return ret_flags;
}
@@ -2785,6 +2790,12 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
	else
		pf->flags &= ~I40E_FLAG_VEB_STATS_ENABLED;

	if ((flags & I40E_PRIV_FLAGS_HW_ATR_EVICT) &&
	    (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE))
		pf->auto_disable_flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE;
	else
		pf->auto_disable_flags |= I40E_FLAG_HW_ATR_EVICT_CAPABLE;

	/* if needed, issue reset to cause things to take effect */
	if (reset_required)
		i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED));
+40 −50
Original line number Diff line number Diff line
@@ -28,11 +28,6 @@
#include <linux/of_net.h>
#include <linux/pci.h>

#ifdef CONFIG_SPARC
#include <asm/idprom.h>
#include <asm/prom.h>
#endif

/* Local includes */
#include "i40e.h"
#include "i40e_diag.h"
@@ -51,7 +46,7 @@ static const char i40e_driver_string[] =

#define DRV_VERSION_MAJOR 1
#define DRV_VERSION_MINOR 4
#define DRV_VERSION_BUILD 11
#define DRV_VERSION_BUILD 12
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
	     __stringify(DRV_VERSION_MINOR) "." \
	     __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -1542,7 +1537,11 @@ static int i40e_set_mac(struct net_device *netdev, void *p)

	ether_addr_copy(netdev->dev_addr, addr->sa_data);

	return i40e_sync_vsi_filters(vsi);
	/* schedule our worker thread which will take care of
	 * applying the new filter changes
	 */
	i40e_service_event_schedule(vsi->back);
	return 0;
}

/**
@@ -1766,6 +1765,11 @@ static void i40e_set_rx_mode(struct net_device *netdev)
		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
		vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
	}

	/* schedule our worker thread which will take care of
	 * applying the new filter changes
	 */
	i40e_service_event_schedule(vsi->back);
}

/**
@@ -1937,7 +1941,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
			    sizeof(struct i40e_aqc_remove_macvlan_element_data);
		del_list_size = filter_list_len *
			    sizeof(struct i40e_aqc_remove_macvlan_element_data);
		del_list = kzalloc(del_list_size, GFP_KERNEL);
		del_list = kzalloc(del_list_size, GFP_ATOMIC);
		if (!del_list) {
			i40e_cleanup_add_list(&tmp_add_list);

@@ -2015,7 +2019,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
			       sizeof(struct i40e_aqc_add_macvlan_element_data),
		add_list_size = filter_list_len *
			       sizeof(struct i40e_aqc_add_macvlan_element_data);
		add_list = kzalloc(add_list_size, GFP_KERNEL);
		add_list = kzalloc(add_list_size, GFP_ATOMIC);
		if (!add_list) {
			/* Purge element from temporary lists */
			i40e_cleanup_add_list(&tmp_add_list);
@@ -3263,22 +3267,6 @@ void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf)
	i40e_flush(hw);
}

/**
 * i40e_irq_dynamic_disable - Disable default interrupt generation settings
 * @vsi: pointer to a vsi
 * @vector: disable a particular Hw Interrupt vector
 **/
void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector)
{
	struct i40e_pf *pf = vsi->back;
	struct i40e_hw *hw = &pf->hw;
	u32 val;

	val = I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
	wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val);
	i40e_flush(hw);
}

/**
 * i40e_msix_clean_rings - MSIX mode Interrupt Handler
 * @irq: interrupt number
@@ -5361,6 +5349,7 @@ int i40e_open(struct net_device *netdev)
	vxlan_get_rx_port(netdev);
#endif
#ifdef CONFIG_I40E_GENEVE
	if (pf->flags & I40E_FLAG_GENEVE_OFFLOAD_CAPABLE)
		geneve_get_rx_port(netdev);
#endif

@@ -6817,12 +6806,12 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
	if (ret)
		goto end_core_reset;

	/* driver is only interested in link up/down and module qualification
	 * reports from firmware
	/* The driver only wants link up/down and module qualification
	 * reports from firmware.  Note the negative logic.
	 */
	ret = i40e_aq_set_phy_int_mask(&pf->hw,
				       I40E_AQ_EVENT_LINK_UPDOWN |
				       I40E_AQ_EVENT_MODULE_QUAL_FAIL, NULL);
				       ~(I40E_AQ_EVENT_LINK_UPDOWN |
					 I40E_AQ_EVENT_MODULE_QUAL_FAIL), NULL);
	if (ret)
		dev_info(&pf->pdev->dev, "set phy mask fail, err %s aq_err %s\n",
			 i40e_stat_str(&pf->hw, ret),
@@ -8465,7 +8454,16 @@ static int i40e_sw_init(struct i40e_pf *pf)
			     I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE |
			     I40E_FLAG_100M_SGMII_CAPABLE |
			     I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
	} else if ((pf->hw.aq.api_maj_ver > 1) ||
		   ((pf->hw.aq.api_maj_ver == 1) &&
		    (pf->hw.aq.api_min_ver > 4))) {
		/* Supported in FW API version higher than 1.4 */
		pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
		pf->auto_disable_flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
	} else {
		pf->auto_disable_flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
	}

	pf->eeprom_version = 0xDEAD;
	pf->lan_veb = I40E_NO_VEB;
	pf->lan_vsi = I40E_NO_VSI;
@@ -8679,6 +8677,9 @@ static void i40e_add_geneve_port(struct net_device *netdev,
	u8 next_idx;
	u8 idx;

	if (!(pf->flags & I40E_FLAG_GENEVE_OFFLOAD_CAPABLE))
		return;

	if (sa_family == AF_INET6)
		return;

@@ -8726,6 +8727,9 @@ static void i40e_del_geneve_port(struct net_device *netdev,
	if (sa_family == AF_INET6)
		return;

	if (!(pf->flags & I40E_FLAG_GENEVE_OFFLOAD_CAPABLE))
		return;

	idx = i40e_get_udp_port_idx(pf, port);

	/* Check if port already exists */
@@ -10609,21 +10613,9 @@ static void i40e_print_features(struct i40e_pf *pf)
 **/
static void i40e_get_platform_mac_addr(struct pci_dev *pdev, struct i40e_pf *pf)
{
	struct device_node *dp = pci_device_to_OF_node(pdev);
	const unsigned char *addr;
	u8 *mac_addr = pf->hw.mac.addr;

	pf->flags &= ~I40E_FLAG_PF_MAC;
	addr = of_get_mac_address(dp);
	if (addr) {
		ether_addr_copy(mac_addr, addr);
		pf->flags |= I40E_FLAG_PF_MAC;
#ifdef CONFIG_SPARC
	} else {
		ether_addr_copy(mac_addr, idprom->id_ethaddr);
	if (!eth_platform_get_mac_address(&pdev->dev, pf->hw.mac.addr))
		pf->flags |= I40E_FLAG_PF_MAC;
#endif /* CONFIG_SPARC */
	}
}

/**
@@ -10952,12 +10944,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
		}
	}

	/* driver is only interested in link up/down and module qualification
	 * reports from firmware
	/* The driver only wants link up/down and module qualification
	 * reports from firmware.  Note the negative logic.
	 */
	err = i40e_aq_set_phy_int_mask(&pf->hw,
				       I40E_AQ_EVENT_LINK_UPDOWN |
				       I40E_AQ_EVENT_MODULE_QUAL_FAIL, NULL);
				       ~(I40E_AQ_EVENT_LINK_UPDOWN |
					 I40E_AQ_EVENT_MODULE_QUAL_FAIL), NULL);
	if (err)
		dev_info(&pf->pdev->dev, "set phy mask fail, err %s aq_err %s\n",
			 i40e_stat_str(&pf->hw, err),
@@ -11008,8 +11000,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	if ((pf->flags & I40E_FLAG_SRIOV_ENABLED) &&
	    (pf->flags & I40E_FLAG_MSIX_ENABLED) &&
	    !test_bit(__I40E_BAD_EEPROM, &pf->state)) {
		u32 val;

		/* disable link interrupts for VFs */
		val = rd32(hw, I40E_PFGEN_PORTMDIO_NUM);
		val &= ~I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK;
Loading