diff options
Diffstat (limited to 'drivers/net/ethernet/intel')
56 files changed, 3168 insertions, 2037 deletions
| diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index c0e17433f623..1349b45f014d 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -58,7 +58,7 @@ config E1000E  	tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"  	depends on PCI && (!SPARC32 || BROKEN)  	select CRC32 -	select PTP_1588_CLOCK +	imply PTP_1588_CLOCK  	---help---  	  This driver supports the PCI-Express Intel(R) PRO/1000 gigabit  	  ethernet family of adapters. For PCI or PCI-X e1000 adapters, @@ -83,7 +83,7 @@ config E1000E_HWTS  config IGB  	tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"  	depends on PCI -	select PTP_1588_CLOCK +	imply PTP_1588_CLOCK  	select I2C  	select I2C_ALGOBIT  	---help--- @@ -156,7 +156,7 @@ config IXGBE  	tristate "Intel(R) 10GbE PCI Express adapters support"  	depends on PCI  	select MDIO -	select PTP_1588_CLOCK +	imply PTP_1588_CLOCK  	---help---  	  This driver supports Intel(R) 10GbE PCI Express family of  	  adapters.  For more information on how to identify your adapter, go @@ -213,7 +213,7 @@ config IXGBEVF  config I40E  	tristate "Intel(R) Ethernet Controller XL710 Family support" -	select PTP_1588_CLOCK +	imply PTP_1588_CLOCK  	depends on PCI  	---help---  	  This driver supports Intel(R) Ethernet Controller XL710 Family of @@ -264,7 +264,7 @@ config FM10K  	tristate "Intel(R) FM10000 Ethernet Switch Host Interface Support"  	default n  	depends on PCI_MSI -	select PTP_1588_CLOCK +	imply PTP_1588_CLOCK  	---help---  	  This driver supports Intel(R) FM10000 Ethernet Switch Host  	  Interface.  For more information on how to identify your adapter, diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 068789e694c9..25c6dfd500b4 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -2286,14 +2286,6 @@ static int e100_set_mac_address(struct net_device *netdev, void *p)  	return 0;  } -static int e100_change_mtu(struct net_device *netdev, int new_mtu) -{ -	if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) -		return -EINVAL; -	netdev->mtu = new_mtu; -	return 0; -} -  static int e100_asf(struct nic *nic)  {  	/* ASF can be enabled from eeprom */ @@ -2834,7 +2826,6 @@ static const struct net_device_ops e100_netdev_ops = {  	.ndo_validate_addr	= eth_validate_addr,  	.ndo_set_rx_mode	= e100_set_multicast_list,  	.ndo_set_mac_address	= e100_set_mac_address, -	.ndo_change_mtu		= e100_change_mtu,  	.ndo_do_ioctl		= e100_do_ioctl,  	.ndo_tx_timeout		= e100_tx_timeout,  #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index f42129d09e2c..93fc6c67306b 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -1085,6 +1085,10 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	    hw->subsystem_vendor_id != PCI_VENDOR_ID_VMWARE)  		netdev->priv_flags |= IFF_UNICAST_FLT; +	/* MTU range: 46 - 16110 */ +	netdev->min_mtu = ETH_ZLEN - ETH_HLEN; +	netdev->max_mtu = MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN); +  	adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);  	/* initialize eeprom parameters */ @@ -3549,13 +3553,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)  {  	struct e1000_adapter *adapter = netdev_priv(netdev);  	struct e1000_hw *hw = &adapter->hw; -	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - -	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || -	    (max_frame > MAX_JUMBO_FRAME_SIZE)) { -		e_err(probe, "Invalid MTU setting\n"); -		return -EINVAL; -	} +	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;  	/* Adapter-specific max frame size limits. */  	switch (hw->mac_type) { @@ -5257,8 +5255,8 @@ static void e1000_netpoll(struct net_device *netdev)  {  	struct e1000_adapter *adapter = netdev_priv(netdev); -	disable_irq(adapter->pdev->irq); -	e1000_intr(adapter->pdev->irq, netdev); +	if (disable_hardirq(adapter->pdev->irq)) +		e1000_intr(adapter->pdev->irq, netdev);  	enable_irq(adapter->pdev->irq);  }  #endif diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 7017281ba2dc..ffcf35af4881 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5974,19 +5974,12 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)  	int max_frame = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;  	/* Jumbo frame support */ -	if ((max_frame > (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)) && +	if ((new_mtu > ETH_DATA_LEN) &&  	    !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {  		e_err("Jumbo Frames not supported.\n");  		return -EINVAL;  	} -	/* Supported frame sizes */ -	if ((new_mtu < (VLAN_ETH_ZLEN + ETH_FCS_LEN)) || -	    (max_frame > adapter->max_hw_frame_size)) { -		e_err("Unsupported MTU setting\n"); -		return -EINVAL; -	} -  	/* Jumbo frame workaround on 82579 and newer requires CRC be stripped */  	if ((adapter->hw.mac.type >= e1000_pch2lan) &&  	    !(adapter->flags2 & FLAG2_CRC_STRIPPING) && @@ -6762,13 +6755,13 @@ static void e1000_netpoll(struct net_device *netdev)  		e1000_intr_msix(adapter->pdev->irq, netdev);  		break;  	case E1000E_INT_MODE_MSI: -		disable_irq(adapter->pdev->irq); -		e1000_intr_msi(adapter->pdev->irq, netdev); +		if (disable_hardirq(adapter->pdev->irq)) +			e1000_intr_msi(adapter->pdev->irq, netdev);  		enable_irq(adapter->pdev->irq);  		break;  	default:		/* E1000E_INT_MODE_LEGACY */ -		disable_irq(adapter->pdev->irq); -		e1000_intr(adapter->pdev->irq, netdev); +		if (disable_hardirq(adapter->pdev->irq)) +			e1000_intr(adapter->pdev->irq, netdev);  		enable_irq(adapter->pdev->irq);  		break;  	} @@ -7187,6 +7180,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  		netdev->vlan_features |= NETIF_F_HIGHDMA;  	} +	/* MTU range: 68 - max_hw_frame_size */ +	netdev->min_mtu = ETH_MIN_MTU; +	netdev->max_mtu = adapter->max_hw_frame_size - +			  (VLAN_ETH_HLEN + ETH_FCS_LEN); +  	if (e1000e_enable_mng_pass_thru(&adapter->hw))  		adapter->flags |= FLAG_MNG_PT_ENABLED; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 05629381be6b..bc5ef6eb3dd6 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -706,16 +706,6 @@ static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev)  	return err;  } -static int fm10k_change_mtu(struct net_device *dev, int new_mtu) -{ -	if (new_mtu < 68 || new_mtu > FM10K_MAX_JUMBO_FRAME_SIZE) -		return -EINVAL; - -	dev->mtu = new_mtu; - -	return 0; -} -  /**   * fm10k_tx_timeout - Respond to a Tx Hang   * @netdev: network interface device structure @@ -1405,7 +1395,6 @@ static const struct net_device_ops fm10k_netdev_ops = {  	.ndo_validate_addr	= eth_validate_addr,  	.ndo_start_xmit		= fm10k_xmit_frame,  	.ndo_set_mac_address	= fm10k_set_mac, -	.ndo_change_mtu		= fm10k_change_mtu,  	.ndo_tx_timeout		= fm10k_tx_timeout,  	.ndo_vlan_rx_add_vid	= fm10k_vlan_rx_add_vid,  	.ndo_vlan_rx_kill_vid	= fm10k_vlan_rx_kill_vid, @@ -1490,5 +1479,9 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)  	dev->hw_features |= hw_features; +	/* MTU range: 68 - 15342 */ +	dev->min_mtu = ETH_MIN_MTU; +	dev->max_mtu = FM10K_MAX_JUMBO_FRAME_SIZE; +  	return dev;  } diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 6d61e443bdf8..ba8d30984bee 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -39,6 +39,7 @@  #include <linux/iommu.h>  #include <linux/slab.h>  #include <linux/list.h> +#include <linux/hashtable.h>  #include <linux/string.h>  #include <linux/in.h>  #include <linux/ip.h> @@ -355,9 +356,11 @@ struct i40e_pf {  #define I40E_FLAG_NO_DCB_SUPPORT		BIT_ULL(45)  #define I40E_FLAG_USE_SET_LLDP_MIB		BIT_ULL(46)  #define I40E_FLAG_STOP_FW_LLDP			BIT_ULL(47) -#define I40E_FLAG_HAVE_10GBASET_PHY		BIT_ULL(48) +#define I40E_FLAG_PHY_CONTROLS_LEDS		BIT_ULL(48)  #define I40E_FLAG_PF_MAC			BIT_ULL(50)  #define I40E_FLAG_TRUE_PROMISC_SUPPORT		BIT_ULL(51) +#define I40E_FLAG_HAVE_CRT_RETIMER		BIT_ULL(52) +#define I40E_FLAG_PTP_L4_CAPABLE		BIT_ULL(53)  	/* tracks features that get auto disabled by errors */  	u64 auto_disable_flags; @@ -428,11 +431,13 @@ struct i40e_pf {  	struct ptp_clock_info ptp_caps;  	struct sk_buff *ptp_tx_skb;  	struct hwtstamp_config tstamp_config; -	unsigned long last_rx_ptp_check; -	spinlock_t tmreg_lock; /* Used to protect the device time registers. */ +	struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */  	u64 ptp_base_adj;  	u32 tx_hwtstamp_timeouts;  	u32 rx_hwtstamp_cleared; +	u32 latch_event_flags; +	spinlock_t ptp_rx_lock; /* Used to protect Rx timestamp registers. */ +	unsigned long latch_events[4];  	bool ptp_tx;  	bool ptp_rx;  	u16 rss_table_size; /* HW RSS table size */ @@ -445,6 +450,20 @@ struct i40e_pf {  	u16 phy_led_val;  }; +/** + * i40e_mac_to_hkey - Convert a 6-byte MAC Address to a u64 hash key + * @macaddr: the MAC Address as the base key + * + * Simply copies the address and returns it as a u64 for hashing + **/ +static inline u64 i40e_addr_to_hkey(const u8 *macaddr) +{ +	u64 key = 0; + +	ether_addr_copy((u8 *)&key, macaddr); +	return key; +} +  enum i40e_filter_state {  	I40E_FILTER_INVALID = 0,	/* Invalid state */  	I40E_FILTER_NEW,		/* New, not sent to FW yet */ @@ -454,13 +473,10 @@ enum i40e_filter_state {  /* There is no 'removed' state; the filter struct is freed */  };  struct i40e_mac_filter { -	struct list_head list; +	struct hlist_node hlist;  	u8 macaddr[ETH_ALEN];  #define I40E_VLAN_ANY -1  	s16 vlan; -	u8 counter;		/* number of instances of this filter */ -	bool is_vf;		/* filter belongs to a VF */ -	bool is_netdev;		/* filter belongs to a netdev */  	enum i40e_filter_state state;  }; @@ -501,9 +517,11 @@ struct i40e_vsi {  #define I40E_VSI_FLAG_VEB_OWNER		BIT(1)  	unsigned long flags; -	/* Per VSI lock to protect elements/list (MAC filter) */ -	spinlock_t mac_filter_list_lock; -	struct list_head mac_filter_list; +	/* Per VSI lock to protect elements/hash (MAC filter) */ +	spinlock_t mac_filter_hash_lock; +	/* Fixed size hash table with 2^8 buckets for MAC filters */ +	DECLARE_HASHTABLE(mac_filter_hash, 8); +	bool has_vlan_filter;  	/* VSI stats */  	struct rtnl_link_stats64 net_stats; @@ -579,6 +597,7 @@ struct i40e_vsi {  	u16 veb_idx;		/* index of VEB parent */  	struct kobject *kobj;	/* sysfs object */  	bool current_isup;	/* Sync 'link up' logging */ +	enum i40e_aq_link_speed current_speed;	/* Sync link speed logging */  	void *priv;	/* client driver data reference. */ @@ -608,6 +627,8 @@ struct i40e_q_vector {  	unsigned long hung_detected; /* Set/Reset for hung_detection logic */  	cpumask_t affinity_mask; +	struct irq_affinity_notify affinity_notify; +  	struct rcu_head rcu;	/* to avoid race with update stats on free */  	char name[I40E_INT_NAME_STR_LEN];  	bool arm_wb_state; @@ -705,6 +726,25 @@ int i40e_get_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);  void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut,  		       u16 rss_table_size, u16 rss_size);  struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id); +/** + * i40e_find_vsi_by_type - Find and return Flow Director VSI + * @pf: PF to search for VSI + * @type: Value indicating type of VSI we are looking for + **/ +static inline struct i40e_vsi * +i40e_find_vsi_by_type(struct i40e_pf *pf, u16 type) +{ +	int i; + +	for (i = 0; i < pf->num_alloc_vsi; i++) { +		struct i40e_vsi *vsi = pf->vsi[i]; + +		if (vsi && vsi->type == type) +			return vsi; +	} + +	return NULL; +}  void i40e_update_stats(struct i40e_vsi *vsi);  void i40e_update_eth_stats(struct i40e_vsi *vsi);  struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi); @@ -721,16 +761,12 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf);  bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);  void i40e_set_ethtool_ops(struct net_device *netdev);  struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, -					u8 *macaddr, s16 vlan, -					bool is_vf, bool is_netdev); -void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan, -		     bool is_vf, bool is_netdev); +					const u8 *macaddr, s16 vlan); +void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan);  int i40e_sync_vsi_filters(struct i40e_vsi *vsi);  struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,  				u16 uplink, u32 param1);  int i40e_vsi_release(struct i40e_vsi *vsi); -struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type, -				 struct i40e_vsi *start_vsi);  #ifdef I40E_FCOE  void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,  			      struct i40e_vsi_context *ctxt, @@ -740,7 +776,8 @@ void i40e_service_event_schedule(struct i40e_pf *pf);  void i40e_notify_client_of_vf_msg(struct i40e_vsi *vsi, u32 vf_id,  				  u8 *msg, u16 len); -int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable); +int i40e_vsi_start_rings(struct i40e_vsi *vsi); +void i40e_vsi_stop_rings(struct i40e_vsi *vsi);  int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count);  struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid,  				u16 downlink_seid, u8 enabled_tc); @@ -815,15 +852,15 @@ int i40e_open(struct net_device *netdev);  int i40e_close(struct net_device *netdev);  int i40e_vsi_open(struct i40e_vsi *vsi);  void i40e_vlan_stripping_disable(struct i40e_vsi *vsi); +int i40e_add_vlan_all_mac(struct i40e_vsi *vsi, s16 vid);  int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid); -int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid); -struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr, -					     bool is_vf, bool is_netdev); -int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, -			  bool is_vf, bool is_netdev); +void i40e_rm_vlan_all_mac(struct i40e_vsi *vsi, s16 vid); +void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid); +struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, +					     const u8 *macaddr); +int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr);  bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi); -struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, -				      bool is_vf, bool is_netdev); +struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);  #ifdef I40E_FCOE  int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,  		    struct tc_to_netdev *tc); diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 738b42a44f20..56fb27298936 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -964,11 +964,11 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,  	desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);  	desc_idx = ntc; +	hw->aq.arq_last_status = +		(enum i40e_admin_queue_err)le16_to_cpu(desc->retval);  	flags = le16_to_cpu(desc->flags);  	if (flags & I40E_AQ_FLAG_ERR) {  		ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; -		hw->aq.arq_last_status = -			(enum i40e_admin_queue_err)le16_to_cpu(desc->retval);  		i40e_debug(hw,  			   I40E_DEBUG_AQ_MESSAGE,  			   "AQRX: Event received with error 0x%X.\n", diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 67e396b2b347..b2101a51534c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1642,6 +1642,10 @@ enum i40e_aq_phy_type {  	I40E_PHY_TYPE_1000BASE_LX		= 0x1C,  	I40E_PHY_TYPE_1000BASE_T_OPTICAL	= 0x1D,  	I40E_PHY_TYPE_20GBASE_KR2		= 0x1E, +	I40E_PHY_TYPE_25GBASE_KR		= 0x1F, +	I40E_PHY_TYPE_25GBASE_CR		= 0x20, +	I40E_PHY_TYPE_25GBASE_SR		= 0x21, +	I40E_PHY_TYPE_25GBASE_LR		= 0x22,  	I40E_PHY_TYPE_MAX  }; @@ -1650,6 +1654,7 @@ enum i40e_aq_phy_type {  #define I40E_LINK_SPEED_10GB_SHIFT	0x3  #define I40E_LINK_SPEED_40GB_SHIFT	0x4  #define I40E_LINK_SPEED_20GB_SHIFT	0x5 +#define I40E_LINK_SPEED_25GB_SHIFT	0x6  enum i40e_aq_link_speed {  	I40E_LINK_SPEED_UNKNOWN	= 0, @@ -1657,7 +1662,8 @@ enum i40e_aq_link_speed {  	I40E_LINK_SPEED_1GB	= BIT(I40E_LINK_SPEED_1000MB_SHIFT),  	I40E_LINK_SPEED_10GB	= BIT(I40E_LINK_SPEED_10GB_SHIFT),  	I40E_LINK_SPEED_40GB	= BIT(I40E_LINK_SPEED_40GB_SHIFT), -	I40E_LINK_SPEED_20GB	= BIT(I40E_LINK_SPEED_20GB_SHIFT) +	I40E_LINK_SPEED_20GB	= BIT(I40E_LINK_SPEED_20GB_SHIFT), +	I40E_LINK_SPEED_25GB	= BIT(I40E_LINK_SPEED_25GB_SHIFT),  };  struct i40e_aqc_module_desc { @@ -1680,6 +1686,8 @@ struct i40e_aq_get_phy_abilities_resp {  #define I40E_AQ_PHY_LINK_ENABLED	0x08  #define I40E_AQ_PHY_AN_ENABLED		0x10  #define I40E_AQ_PHY_FLAG_MODULE_QUAL	0x20 +#define I40E_AQ_PHY_FEC_ABILITY_KR	0x40 +#define I40E_AQ_PHY_FEC_ABILITY_RS	0x80  	__le16	eee_capability;  #define I40E_AQ_EEE_100BASE_TX		0x0002  #define I40E_AQ_EEE_1000BASE_T		0x0004 @@ -1690,7 +1698,22 @@ struct i40e_aq_get_phy_abilities_resp {  	__le32	eeer_val;  	u8	d3_lpan;  #define I40E_AQ_SET_PHY_D3_LPAN_ENA	0x01 -	u8	reserved[3]; +	u8	phy_type_ext; +#define I40E_AQ_PHY_TYPE_EXT_25G_KR	0X01 +#define I40E_AQ_PHY_TYPE_EXT_25G_CR	0X02 +#define I40E_AQ_PHY_TYPE_EXT_25G_SR	0x04 +#define I40E_AQ_PHY_TYPE_EXT_25G_LR	0x08 +	u8	fec_cfg_curr_mod_ext_info; +#define I40E_AQ_ENABLE_FEC_KR		0x01 +#define I40E_AQ_ENABLE_FEC_RS		0x02 +#define I40E_AQ_REQUEST_FEC_KR		0x04 +#define I40E_AQ_REQUEST_FEC_RS		0x08 +#define I40E_AQ_ENABLE_FEC_AUTO		0x10 +#define I40E_AQ_FEC +#define I40E_AQ_MODULE_TYPE_EXT_MASK	0xE0 +#define I40E_AQ_MODULE_TYPE_EXT_SHIFT	5 + +	u8	ext_comp_code;  	u8	phy_id[4];  	u8	module_type[3];  	u8	qualified_module_count; @@ -1712,7 +1735,20 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */  	__le16	eee_capability;  	__le32	eeer;  	u8	low_power_ctrl; -	u8	reserved[3]; +	u8	phy_type_ext; +#define I40E_AQ_PHY_TYPE_EXT_25G_KR	0X01 +#define I40E_AQ_PHY_TYPE_EXT_25G_CR	0X02 +#define I40E_AQ_PHY_TYPE_EXT_25G_SR	0x04 +#define I40E_AQ_PHY_TYPE_EXT_25G_LR	0x08 +	u8	fec_config; +#define I40E_AQ_SET_FEC_ABILITY_KR	BIT(0) +#define I40E_AQ_SET_FEC_ABILITY_RS	BIT(1) +#define I40E_AQ_SET_FEC_REQUEST_KR	BIT(2) +#define I40E_AQ_SET_FEC_REQUEST_RS	BIT(3) +#define I40E_AQ_SET_FEC_AUTO		BIT(4) +#define I40E_AQ_PHY_FEC_CONFIG_SHIFT	0x0 +#define I40E_AQ_PHY_FEC_CONFIG_MASK	(0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT) +	u8	reserved;  };  I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config); @@ -1792,9 +1828,18 @@ struct i40e_aqc_get_link_status {  #define I40E_AQ_LINK_TX_DRAINED		0x01  #define I40E_AQ_LINK_TX_FLUSHED		0x03  #define I40E_AQ_LINK_FORCED_40G		0x10 +/* 25G Error Codes */ +#define I40E_AQ_25G_NO_ERR		0X00 +#define I40E_AQ_25G_NOT_PRESENT		0X01 +#define I40E_AQ_25G_NVM_CRC_ERR		0X02 +#define I40E_AQ_25G_SBUS_UCODE_ERR	0X03 +#define I40E_AQ_25G_SERDES_UCODE_ERR	0X04 +#define I40E_AQ_25G_NIMB_UCODE_ERR	0X05  	u8	loopback; /* use defines from i40e_aqc_set_lb_mode */  	__le16	max_frame_size;  	u8	config; +#define I40E_AQ_CONFIG_FEC_KR_ENA	0x01 +#define I40E_AQ_CONFIG_FEC_RS_ENA	0x02  #define I40E_AQ_CONFIG_CRC_ENA		0x04  #define I40E_AQ_CONFIG_PACING_MASK	0x78  	u8	external_power_ability; diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c index 250db0b244b7..7fe72abc0b4a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_client.c +++ b/drivers/net/ethernet/intel/i40e/i40e_client.c @@ -287,6 +287,7 @@ void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset)  			}  			cdev->client->ops->close(&cdev->lan_info, cdev->client,  						 reset); +			clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);  			i40e_client_release_qvlist(&cdev->lan_info);  		}  	} @@ -406,37 +407,6 @@ int i40e_vf_client_capable(struct i40e_pf *pf, u32 vf_id,  }  /** - * i40e_vsi_lookup - finds a matching VSI from the PF list starting at start_vsi - * @pf: board private structure - * @type: vsi type - * @start_vsi: a VSI pointer from where to start the search - * - * Returns non NULL on success or NULL for failure - **/ -struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, -				 enum i40e_vsi_type type, -				 struct i40e_vsi *start_vsi) -{ -	struct i40e_vsi *vsi; -	int i = 0; - -	if (start_vsi) { -		for (i = 0; i < pf->num_alloc_vsi; i++) { -			vsi = pf->vsi[i]; -			if (vsi == start_vsi) -				break; -		} -	} -	for (; i < pf->num_alloc_vsi; i++) { -		vsi = pf->vsi[i]; -		if (vsi && vsi->type == type) -			return vsi; -	} - -	return NULL; -} - -/**   * i40e_client_add_instance - add a client instance struct to the instance list   * @pf: pointer to the board struct   * @client: pointer to a client struct in the client list. @@ -565,7 +535,7 @@ void i40e_client_subtask(struct i40e_pf *pf)  			if (test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state))  				continue;  		} else { -			dev_warn(&pf->pdev->dev, "This client %s is being instanciated at probe\n", +			dev_warn(&pf->pdev->dev, "This client %s is being instantiated at probe\n",  				 client->name);  		} @@ -575,29 +545,25 @@ void i40e_client_subtask(struct i40e_pf *pf)  			continue;  		if (!existing) { -			/* Also up the ref_cnt for no. of instances of this -			 * client. -			 */ -			atomic_inc(&client->ref_cnt);  			dev_info(&pf->pdev->dev, "Added instance of Client %s to PF%d bus=0x%02x func=0x%02x\n",  				 client->name, pf->hw.pf_id,  				 pf->hw.bus.device, pf->hw.bus.func);  		}  		mutex_lock(&i40e_client_instance_mutex); -		/* Send an Open request to the client */ -		atomic_inc(&cdev->ref_cnt); -		if (client->ops && client->ops->open) -			ret = client->ops->open(&cdev->lan_info, client); -		atomic_dec(&cdev->ref_cnt); -		if (!ret) { -			set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state); -		} else { -			/* remove client instance */ -			mutex_unlock(&i40e_client_instance_mutex); -			i40e_client_del_instance(pf, client); -			atomic_dec(&client->ref_cnt); -			continue; +		if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, +			      &cdev->state)) { +			/* Send an Open request to the client */ +			if (client->ops && client->ops->open) +				ret = client->ops->open(&cdev->lan_info, +							client); +			if (!ret) { +				set_bit(__I40E_CLIENT_INSTANCE_OPENED, +					&cdev->state); +			} else { +				/* remove client instance */ +				i40e_client_del_instance(pf, client); +			}  		}  		mutex_unlock(&i40e_client_instance_mutex);  	} @@ -694,10 +660,6 @@ static int i40e_client_release(struct i40e_client *client)  			continue;  		pf = (struct i40e_pf *)cdev->lan_info.pf;  		if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) { -			if (atomic_read(&cdev->ref_cnt) > 0) { -				ret = I40E_ERR_NOT_READY; -				goto out; -			}  			if (client->ops && client->ops->close)  				client->ops->close(&cdev->lan_info, client,  						   false); @@ -710,11 +672,9 @@ static int i40e_client_release(struct i40e_client *client)  		}  		/* delete the client instance from the list */  		list_move(&cdev->list, &cdevs_tmp); -		atomic_dec(&client->ref_cnt);  		dev_info(&pf->pdev->dev, "Deleted client instance of Client %s\n",  			 client->name);  	} -out:  	mutex_unlock(&i40e_client_instance_mutex);  	/* free the client device and release its vsi */ @@ -1040,17 +1000,10 @@ int i40e_unregister_client(struct i40e_client *client)  		ret = -ENODEV;  		goto out;  	} -	if (atomic_read(&client->ref_cnt) == 0) { -		clear_bit(__I40E_CLIENT_REGISTERED, &client->state); -		list_del(&client->list); -		pr_info("i40e: Unregistered client %s with return code %d\n", -			client->name, ret); -	} else { -		ret = I40E_ERR_NOT_READY; -		pr_err("i40e: Client %s failed unregister - client has open instances\n", -		       client->name); -	} - +	clear_bit(__I40E_CLIENT_REGISTERED, &client->state); +	list_del(&client->list); +	pr_info("i40e: Unregistered client %s with return code %d\n", +		client->name, ret);  out:  	mutex_unlock(&i40e_client_mutex);  	return ret; diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.h b/drivers/net/ethernet/intel/i40e/i40e_client.h index 38a6c36a6a0e..528bd79b05fe 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_client.h +++ b/drivers/net/ethernet/intel/i40e/i40e_client.h @@ -203,8 +203,6 @@ struct i40e_client_instance {  	struct i40e_info lan_info;  	struct i40e_client *client;  	unsigned long  state; -	/* A count of all the in-progress calls to the client */ -	atomic_t ref_cnt;  };  struct i40e_client { diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 2154a34c1dd8..128735975caa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -53,6 +53,8 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw)  		case I40E_DEV_ID_10G_BASE_T4:  		case I40E_DEV_ID_20G_KR2:  		case I40E_DEV_ID_20G_KR2_A: +		case I40E_DEV_ID_25G_B: +		case I40E_DEV_ID_25G_SFP28:  			hw->mac.type = I40E_MAC_XL710;  			break;  		case I40E_DEV_ID_KX_X722: @@ -1183,6 +1185,8 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)  	case I40E_PHY_TYPE_1000BASE_LX:  	case I40E_PHY_TYPE_40GBASE_SR4:  	case I40E_PHY_TYPE_40GBASE_LR4: +	case I40E_PHY_TYPE_25GBASE_LR: +	case I40E_PHY_TYPE_25GBASE_SR:  		media = I40E_MEDIA_TYPE_FIBER;  		break;  	case I40E_PHY_TYPE_100BASE_TX: @@ -1197,6 +1201,7 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)  	case I40E_PHY_TYPE_10GBASE_SFPP_CU:  	case I40E_PHY_TYPE_40GBASE_AOC:  	case I40E_PHY_TYPE_10GBASE_AOC: +	case I40E_PHY_TYPE_25GBASE_CR:  		media = I40E_MEDIA_TYPE_DA;  		break;  	case I40E_PHY_TYPE_1000BASE_KX: @@ -1204,6 +1209,7 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)  	case I40E_PHY_TYPE_10GBASE_KR:  	case I40E_PHY_TYPE_40GBASE_KR4:  	case I40E_PHY_TYPE_20GBASE_KR2: +	case I40E_PHY_TYPE_25GBASE_KR:  		media = I40E_MEDIA_TYPE_BACKPLANE;  		break;  	case I40E_PHY_TYPE_SGMII: @@ -1608,8 +1614,10 @@ i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw,  	if (hw->aq.asq_last_status == I40E_AQ_RC_EIO)  		status = I40E_ERR_UNKNOWN_PHY; -	if (report_init) +	if (report_init) {  		hw->phy.phy_types = le32_to_cpu(abilities->phy_type); +		hw->phy.phy_types |= ((u64)abilities->phy_type_ext << 32); +	}  	return status;  } @@ -1701,10 +1709,13 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,  			config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;  		/* Copy over all the old settings */  		config.phy_type = abilities.phy_type; +		config.phy_type_ext = abilities.phy_type_ext;  		config.link_speed = abilities.link_speed;  		config.eee_capability = abilities.eee_capability;  		config.eeer = abilities.eeer_val;  		config.low_power_ctrl = abilities.d3_lpan; +		config.fec_config = abilities.fec_cfg_curr_mod_ext_info & +				    I40E_AQ_PHY_FEC_CONFIG_MASK;  		status = i40e_aq_set_phy_config(hw, &config, NULL);  		if (status) @@ -1849,12 +1860,13 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,  	else  		hw_link_info->crc_enable = false; -	if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_ENABLE)) +	if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_IS_ENABLED))  		hw_link_info->lse_enable = true;  	else  		hw_link_info->lse_enable = false; -	if ((hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 && +	if ((hw->mac.type == I40E_MAC_XL710) && +	    (hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 &&  	     hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)  		hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU; @@ -2169,6 +2181,40 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,  }  /** + * i40e_aq_set_vsi_bc_promisc_on_vlan + * @hw: pointer to the hw struct + * @seid: vsi number + * @enable: set broadcast promiscuous enable/disable for a given VLAN + * @vid: The VLAN tag filter - capture any broadcast packet with this VLAN tag + * @cmd_details: pointer to command details structure or NULL + **/ +i40e_status i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw, +				u16 seid, bool enable, u16 vid, +				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_BROADCAST; + +	cmd->promiscuous_flags = cpu_to_le16(flags); +	cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_BROADCAST); +	cmd->seid = cpu_to_le16(seid); +	cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID); + +	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + +	return status; +} + +/**   * i40e_aq_set_vsi_broadcast   * @hw: pointer to the hw struct   * @seid: vsi number @@ -2494,7 +2540,10 @@ i40e_status i40e_update_link_info(struct i40e_hw *hw)  	if (status)  		return status; -	if (hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) { +	/* extra checking needed to ensure link info to user is timely */ +	if ((hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) && +	    ((hw->phy.link_info.link_info & I40E_AQ_LINK_UP) || +	     !(hw->phy.link_info_old.link_info & I40E_AQ_LINK_UP))) {  		status = i40e_aq_get_phy_capabilities(hw, false, false,  						      &abilities, NULL);  		if (status) @@ -3144,6 +3193,14 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,  			break;  		case I40E_AQ_CAP_ID_MNG_MODE:  			p->management_mode = number; +			if (major_rev > 1) { +				p->mng_protocols_over_mctp = logical_id; +				i40e_debug(hw, I40E_DEBUG_INIT, +					   "HW Capability: Protocols over MCTP = %d\n", +					   p->mng_protocols_over_mctp); +			} else { +				p->mng_protocols_over_mctp = 0; +			}  			break;  		case I40E_AQ_CAP_ID_NPAR_ACTIVE:  			p->npar_enable = number; @@ -3310,8 +3367,10 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,  	/* partition id is 1-based, and functions are evenly spread  	 * across the ports as partitions  	 */ -	hw->partition_id = (hw->pf_id / hw->num_ports) + 1; -	hw->num_partitions = num_functions / hw->num_ports; +	if (hw->num_ports != 0) { +		hw->partition_id = (hw->pf_id / hw->num_ports) + 1; +		hw->num_partitions = num_functions / hw->num_ports; +	}  	/* additional HW specific goodies that might  	 * someday be HW version specific @@ -4391,7 +4450,92 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,  }  /** - * i40e_read_phy_register + * i40e_read_phy_register_clause22 + * @hw: pointer to the HW structure + * @reg: register address in the page + * @phy_adr: PHY address on MDIO interface + * @value: PHY register value + * + * Reads specified PHY register value + **/ +i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw, +					    u16 reg, u8 phy_addr, u16 *value) +{ +	i40e_status status = I40E_ERR_TIMEOUT; +	u8 port_num = (u8)hw->func_caps.mdio_port_num; +	u32 command = 0; +	u16 retry = 1000; + +	command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) | +		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | +		  (I40E_MDIO_CLAUSE22_OPCODE_READ_MASK) | +		  (I40E_MDIO_CLAUSE22_STCODE_MASK) | +		  (I40E_GLGEN_MSCA_MDICMD_MASK); +	wr32(hw, I40E_GLGEN_MSCA(port_num), command); +	do { +		command = rd32(hw, I40E_GLGEN_MSCA(port_num)); +		if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) { +			status = 0; +			break; +		} +		udelay(10); +		retry--; +	} while (retry); + +	if (status) { +		i40e_debug(hw, I40E_DEBUG_PHY, +			   "PHY: Can't write command to external PHY.\n"); +	} else { +		command = rd32(hw, I40E_GLGEN_MSRWD(port_num)); +		*value = (command & I40E_GLGEN_MSRWD_MDIRDDATA_MASK) >> +			 I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT; +	} + +	return status; +} + +/** + * i40e_write_phy_register_clause22 + * @hw: pointer to the HW structure + * @reg: register address in the page + * @phy_adr: PHY address on MDIO interface + * @value: PHY register value + * + * Writes specified PHY register value + **/ +i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw, +					     u16 reg, u8 phy_addr, u16 value) +{ +	i40e_status status = I40E_ERR_TIMEOUT; +	u8 port_num = (u8)hw->func_caps.mdio_port_num; +	u32 command  = 0; +	u16 retry = 1000; + +	command = value << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT; +	wr32(hw, I40E_GLGEN_MSRWD(port_num), command); + +	command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) | +		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | +		  (I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK) | +		  (I40E_MDIO_CLAUSE22_STCODE_MASK) | +		  (I40E_GLGEN_MSCA_MDICMD_MASK); + +	wr32(hw, I40E_GLGEN_MSCA(port_num), command); +	do { +		command = rd32(hw, I40E_GLGEN_MSCA(port_num)); +		if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) { +			status = 0; +			break; +		} +		udelay(10); +		retry--; +	} while (retry); + +	return status; +} + +/** + * i40e_read_phy_register_clause45   * @hw: pointer to the HW structure   * @page: registers page number   * @reg: register address in the page @@ -4400,9 +4544,8 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,   *   * Reads specified PHY register value   **/ -i40e_status i40e_read_phy_register(struct i40e_hw *hw, -				   u8 page, u16 reg, u8 phy_addr, -				   u16 *value) +i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw, +				u8 page, u16 reg, u8 phy_addr, u16 *value)  {  	i40e_status status = I40E_ERR_TIMEOUT;  	u32 command = 0; @@ -4412,8 +4555,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,  	command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |  		  (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |  		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | -		  (I40E_MDIO_OPCODE_ADDRESS) | -		  (I40E_MDIO_STCODE) | +		  (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) | +		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |  		  (I40E_GLGEN_MSCA_MDICMD_MASK) |  		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);  	wr32(hw, I40E_GLGEN_MSCA(port_num), command); @@ -4435,8 +4578,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,  	command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |  		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | -		  (I40E_MDIO_OPCODE_READ) | -		  (I40E_MDIO_STCODE) | +		  (I40E_MDIO_CLAUSE45_OPCODE_READ_MASK) | +		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |  		  (I40E_GLGEN_MSCA_MDICMD_MASK) |  		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);  	status = I40E_ERR_TIMEOUT; @@ -4466,7 +4609,7 @@ phy_read_end:  }  /** - * i40e_write_phy_register + * i40e_write_phy_register_clause45   * @hw: pointer to the HW structure   * @page: registers page number   * @reg: register address in the page @@ -4475,9 +4618,8 @@ phy_read_end:   *   * Writes value to specified PHY register   **/ -i40e_status i40e_write_phy_register(struct i40e_hw *hw, -				    u8 page, u16 reg, u8 phy_addr, -				    u16 value) +i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw, +				u8 page, u16 reg, u8 phy_addr, u16 value)  {  	i40e_status status = I40E_ERR_TIMEOUT;  	u32 command = 0; @@ -4487,8 +4629,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,  	command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |  		  (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |  		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | -		  (I40E_MDIO_OPCODE_ADDRESS) | -		  (I40E_MDIO_STCODE) | +		  (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) | +		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |  		  (I40E_GLGEN_MSCA_MDICMD_MASK) |  		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);  	wr32(hw, I40E_GLGEN_MSCA(port_num), command); @@ -4512,8 +4654,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,  	command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |  		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | -		  (I40E_MDIO_OPCODE_WRITE) | -		  (I40E_MDIO_STCODE) | +		  (I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK) | +		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |  		  (I40E_GLGEN_MSCA_MDICMD_MASK) |  		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);  	status = I40E_ERR_TIMEOUT; @@ -4534,6 +4676,78 @@ phy_write_end:  }  /** + * i40e_write_phy_register + * @hw: pointer to the HW structure + * @page: registers page number + * @reg: register address in the page + * @phy_adr: PHY address on MDIO interface + * @value: PHY register value + * + * Writes value to specified PHY register + **/ +i40e_status i40e_write_phy_register(struct i40e_hw *hw, +				    u8 page, u16 reg, u8 phy_addr, u16 value) +{ +	i40e_status status; + +	switch (hw->device_id) { +	case I40E_DEV_ID_1G_BASE_T_X722: +		status = i40e_write_phy_register_clause22(hw, reg, phy_addr, +							  value); +		break; +	case I40E_DEV_ID_10G_BASE_T: +	case I40E_DEV_ID_10G_BASE_T4: +	case I40E_DEV_ID_10G_BASE_T_X722: +	case I40E_DEV_ID_25G_B: +	case I40E_DEV_ID_25G_SFP28: +		status = i40e_write_phy_register_clause45(hw, page, reg, +							  phy_addr, value); +		break; +	default: +		status = I40E_ERR_UNKNOWN_PHY; +		break; +	} + +	return status; +} + +/** + * i40e_read_phy_register + * @hw: pointer to the HW structure + * @page: registers page number + * @reg: register address in the page + * @phy_adr: PHY address on MDIO interface + * @value: PHY register value + * + * Reads specified PHY register value + **/ +i40e_status i40e_read_phy_register(struct i40e_hw *hw, +				   u8 page, u16 reg, u8 phy_addr, u16 *value) +{ +	i40e_status status; + +	switch (hw->device_id) { +	case I40E_DEV_ID_1G_BASE_T_X722: +		status = i40e_read_phy_register_clause22(hw, reg, phy_addr, +							 value); +		break; +	case I40E_DEV_ID_10G_BASE_T: +	case I40E_DEV_ID_10G_BASE_T4: +	case I40E_DEV_ID_10G_BASE_T_X722: +	case I40E_DEV_ID_25G_B: +	case I40E_DEV_ID_25G_SFP28: +		status = i40e_read_phy_register_clause45(hw, page, reg, +							 phy_addr, value); +		break; +	default: +		status = I40E_ERR_UNKNOWN_PHY; +		break; +	} + +	return status; +} + +/**   * i40e_get_phy_address   * @hw: pointer to the HW structure   * @dev_num: PHY port num that address we want @@ -4575,14 +4789,16 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,  	for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,  	     led_addr++) { -		status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, -						led_addr, phy_addr, &led_reg); +		status = i40e_read_phy_register_clause45(hw, +							 I40E_PHY_COM_REG_PAGE, +							 led_addr, phy_addr, +							 &led_reg);  		if (status)  			goto phy_blinking_end;  		led_ctl = led_reg;  		if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {  			led_reg = 0; -			status = i40e_write_phy_register(hw, +			status = i40e_write_phy_register_clause45(hw,  							 I40E_PHY_COM_REG_PAGE,  							 led_addr, phy_addr,  							 led_reg); @@ -4594,20 +4810,18 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,  	if (time > 0 && interval > 0) {  		for (i = 0; i < time * 1000; i += interval) { -			status = i40e_read_phy_register(hw, -							I40E_PHY_COM_REG_PAGE, -							led_addr, phy_addr, -							&led_reg); +			status = i40e_read_phy_register_clause45(hw, +						I40E_PHY_COM_REG_PAGE, +						led_addr, phy_addr, &led_reg);  			if (status)  				goto restore_config;  			if (led_reg & I40E_PHY_LED_MANUAL_ON)  				led_reg = 0;  			else  				led_reg = I40E_PHY_LED_MANUAL_ON; -			status = i40e_write_phy_register(hw, -							 I40E_PHY_COM_REG_PAGE, -							 led_addr, phy_addr, -							 led_reg); +			status = i40e_write_phy_register_clause45(hw, +						I40E_PHY_COM_REG_PAGE, +						led_addr, phy_addr, led_reg);  			if (status)  				goto restore_config;  			msleep(interval); @@ -4615,8 +4829,9 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,  	}  restore_config: -	status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, -					 phy_addr, led_ctl); +	status = i40e_write_phy_register_clause45(hw, +						  I40E_PHY_COM_REG_PAGE, +						  led_addr, phy_addr, led_ctl);  phy_blinking_end:  	return status; @@ -4647,8 +4862,10 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,  	for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,  	     temp_addr++) { -		status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, -						temp_addr, phy_addr, ®_val); +		status = i40e_read_phy_register_clause45(hw, +							 I40E_PHY_COM_REG_PAGE, +							 temp_addr, phy_addr, +							 ®_val);  		if (status)  			return status;  		*val = reg_val; @@ -4681,41 +4898,42 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,  	i = rd32(hw, I40E_PFGEN_PORTNUM);  	port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);  	phy_addr = i40e_get_phy_address(hw, port_num); - -	status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, -					phy_addr, &led_reg); +	status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE, +						 led_addr, phy_addr, &led_reg);  	if (status)  		return status;  	led_ctl = led_reg;  	if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {  		led_reg = 0; -		status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, -						 led_addr, phy_addr, led_reg); +		status = i40e_write_phy_register_clause45(hw, +							  I40E_PHY_COM_REG_PAGE, +							  led_addr, phy_addr, +							  led_reg);  		if (status)  			return status;  	} -	status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, -					led_addr, phy_addr, &led_reg); +	status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE, +						 led_addr, phy_addr, &led_reg);  	if (status)  		goto restore_config;  	if (on)  		led_reg = I40E_PHY_LED_MANUAL_ON;  	else  		led_reg = 0; -	status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, -					 led_addr, phy_addr, led_reg); +	status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE, +						  led_addr, phy_addr, led_reg);  	if (status)  		goto restore_config;  	if (mode & I40E_PHY_LED_MODE_ORIG) {  		led_ctl = (mode & I40E_PHY_LED_MODE_MASK); -		status = i40e_write_phy_register(hw, +		status = i40e_write_phy_register_clause45(hw,  						 I40E_PHY_COM_REG_PAGE,  						 led_addr, phy_addr, led_ctl);  	}  	return status;  restore_config: -	status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, -					 phy_addr, led_ctl); +	status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE, +						  led_addr, phy_addr, led_ctl);  	return status;  } diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 0c1875b5b16d..f1f41f12902f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -134,7 +134,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)  	struct rtnl_link_stats64 *nstat;  	struct i40e_mac_filter *f;  	struct i40e_vsi *vsi; -	int i; +	int i, bkt;  	vsi = i40e_dbg_find_vsi(pf, seid);  	if (!vsi) { @@ -166,13 +166,13 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)  			 pf->hw.mac.addr,  			 pf->hw.mac.san_addr,  			 pf->hw.mac.port_addr); -	list_for_each_entry(f, &vsi->mac_filter_list, list) { +	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {  		dev_info(&pf->pdev->dev, -			 "    mac_filter_list: %pM vid=%d, is_netdev=%d is_vf=%d counter=%d, state %s\n", -			 f->macaddr, f->vlan, f->is_netdev, f->is_vf, -			 f->counter, i40e_filter_state_string[f->state]); +			 "    mac_filter_hash: %pM vid=%d, state %s\n", +			 f->macaddr, f->vlan, +			 i40e_filter_state_string[f->state]);  	} -	dev_info(&pf->pdev->dev, "    active_filters %d, promisc_threshold %d, overflow promisc %s\n", +	dev_info(&pf->pdev->dev, "    active_filters %u, promisc_threshold %u, overflow promisc %s\n",  		 vsi->active_filters, vsi->promisc_threshold,  		 (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) ?  		  "ON" : "OFF")); @@ -867,86 +867,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,  		dev_info(&pf->pdev->dev, "deleting relay %d\n", veb_seid);  		i40e_veb_release(pf->veb[i]); - -	} else if (strncmp(cmd_buf, "add macaddr", 11) == 0) { -		struct i40e_mac_filter *f; -		int vlan = 0; -		u8 ma[6]; -		int ret; - -		cnt = sscanf(&cmd_buf[11], -			     "%i %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %i", -			     &vsi_seid, -			     &ma[0], &ma[1], &ma[2], &ma[3], &ma[4], &ma[5], -			     &vlan); -		if (cnt == 7) { -			vlan = 0; -		} else if (cnt != 8) { -			dev_info(&pf->pdev->dev, -				 "add macaddr: bad command string, cnt=%d\n", -				 cnt); -			goto command_write_done; -		} - -		vsi = i40e_dbg_find_vsi(pf, vsi_seid); -		if (!vsi) { -			dev_info(&pf->pdev->dev, -				 "add macaddr: VSI %d not found\n", vsi_seid); -			goto command_write_done; -		} - -		spin_lock_bh(&vsi->mac_filter_list_lock); -		f = i40e_add_filter(vsi, ma, vlan, false, false); -		spin_unlock_bh(&vsi->mac_filter_list_lock); -		ret = i40e_sync_vsi_filters(vsi); -		if (f && !ret) -			dev_info(&pf->pdev->dev, -				 "add macaddr: %pM vlan=%d added to VSI %d\n", -				 ma, vlan, vsi_seid); -		else -			dev_info(&pf->pdev->dev, -				 "add macaddr: %pM vlan=%d to VSI %d failed, f=%p ret=%d\n", -				 ma, vlan, vsi_seid, f, ret); - -	} else if (strncmp(cmd_buf, "del macaddr", 11) == 0) { -		int vlan = 0; -		u8 ma[6]; -		int ret; - -		cnt = sscanf(&cmd_buf[11], -			     "%i %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %i", -			     &vsi_seid, -			     &ma[0], &ma[1], &ma[2], &ma[3], &ma[4], &ma[5], -			     &vlan); -		if (cnt == 7) { -			vlan = 0; -		} else if (cnt != 8) { -			dev_info(&pf->pdev->dev, -				 "del macaddr: bad command string, cnt=%d\n", -				 cnt); -			goto command_write_done; -		} - -		vsi = i40e_dbg_find_vsi(pf, vsi_seid); -		if (!vsi) { -			dev_info(&pf->pdev->dev, -				 "del macaddr: VSI %d not found\n", vsi_seid); -			goto command_write_done; -		} - -		spin_lock_bh(&vsi->mac_filter_list_lock); -		i40e_del_filter(vsi, ma, vlan, false, false); -		spin_unlock_bh(&vsi->mac_filter_list_lock); -		ret = i40e_sync_vsi_filters(vsi); -		if (!ret) -			dev_info(&pf->pdev->dev, -				 "del macaddr: %pM vlan=%d removed from VSI %d\n", -				 ma, vlan, vsi_seid); -		else -			dev_info(&pf->pdev->dev, -				 "del macaddr: %pM vlan=%d from VSI %d failed, ret=%d\n", -				 ma, vlan, vsi_seid, ret); -  	} else if (strncmp(cmd_buf, "add pvid", 8) == 0) {  		i40e_status ret;  		u16 vid; @@ -1210,24 +1130,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,  			dev_info(&pf->pdev->dev,  				 "dump debug fwdata <cluster_id> <table_id> <index>\n");  		} - -	} else if (strncmp(cmd_buf, "msg_enable", 10) == 0) { -		u32 level; -		cnt = sscanf(&cmd_buf[10], "%i", &level); -		if (cnt) { -			if (I40E_DEBUG_USER & level) { -				pf->hw.debug_mask = level; -				dev_info(&pf->pdev->dev, -					 "set hw.debug_mask = 0x%08x\n", -					 pf->hw.debug_mask); -			} -			pf->msg_enable = level; -			dev_info(&pf->pdev->dev, "set msg_enable = 0x%08x\n", -				 pf->msg_enable); -		} else { -			dev_info(&pf->pdev->dev, "msg_enable = 0x%08x\n", -				 pf->msg_enable); -		}  	} else if (strncmp(cmd_buf, "pfr", 3) == 0) {  		dev_info(&pf->pdev->dev, "debugfs: forcing PFR\n");  		i40e_do_reset_safe(pf, BIT(__I40E_PF_RESET_REQUESTED)); @@ -1633,8 +1535,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,  		dev_info(&pf->pdev->dev, "  del vsi [vsi_seid]\n");  		dev_info(&pf->pdev->dev, "  add relay <uplink_seid> <vsi_seid>\n");  		dev_info(&pf->pdev->dev, "  del relay <relay_seid>\n"); -		dev_info(&pf->pdev->dev, "  add macaddr <vsi_seid> <aa:bb:cc:dd:ee:ff> [vlan]\n"); -		dev_info(&pf->pdev->dev, "  del macaddr <vsi_seid> <aa:bb:cc:dd:ee:ff> [vlan]\n");  		dev_info(&pf->pdev->dev, "  add pvid <vsi_seid> <vid>\n");  		dev_info(&pf->pdev->dev, "  del pvid <vsi_seid>\n");  		dev_info(&pf->pdev->dev, "  dump switch\n"); @@ -1644,7 +1544,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,  		dev_info(&pf->pdev->dev, "  dump desc aq\n");  		dev_info(&pf->pdev->dev, "  dump reset stats\n");  		dev_info(&pf->pdev->dev, "  dump debug fwdata <cluster_id> <table_id> <index>\n"); -		dev_info(&pf->pdev->dev, "  msg_enable [level]\n");  		dev_info(&pf->pdev->dev, "  read <reg>\n");  		dev_info(&pf->pdev->dev, "  write <reg> <value>\n");  		dev_info(&pf->pdev->dev, "  clear_stats vsi [seid]\n"); diff --git a/drivers/net/ethernet/intel/i40e/i40e_devids.h b/drivers/net/ethernet/intel/i40e/i40e_devids.h index dd4457d29e98..8e46098bad57 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_devids.h +++ b/drivers/net/ethernet/intel/i40e/i40e_devids.h @@ -39,6 +39,8 @@  #define I40E_DEV_ID_20G_KR2		0x1587  #define I40E_DEV_ID_20G_KR2_A		0x1588  #define I40E_DEV_ID_10G_BASE_T4		0x1589 +#define I40E_DEV_ID_25G_B		0x158A +#define I40E_DEV_ID_25G_SFP28		0x158B  #define I40E_DEV_ID_KX_X722		0x37CE  #define I40E_DEV_ID_QSFP_X722		0x37CF  #define I40E_DEV_ID_SFP_X722		0x37D0 diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 92bc8846f1ba..cc1465aac2ef 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -104,7 +104,7 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {   * The PF_STATs are appended to the netdev stats only when ethtool -S   * is queried on the base PF netdev, not on the VMDq or FCoE netdev.   */ -static struct i40e_stats i40e_gstrings_stats[] = { +static const struct i40e_stats i40e_gstrings_stats[] = {  	I40E_PF_STAT("rx_bytes", stats.eth.rx_bytes),  	I40E_PF_STAT("tx_bytes", stats.eth.tx_bytes),  	I40E_PF_STAT("rx_unicast", stats.eth.rx_unicast), @@ -216,7 +216,6 @@ enum i40e_ethtool_test_id {  	I40E_ETH_TEST_REG = 0,  	I40E_ETH_TEST_EEPROM,  	I40E_ETH_TEST_INTR, -	I40E_ETH_TEST_LOOPBACK,  	I40E_ETH_TEST_LINK,  }; @@ -224,32 +223,27 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = {  	"Register test  (offline)",  	"Eeprom test    (offline)",  	"Interrupt test (offline)", -	"Loopback test  (offline)",  	"Link test   (on/offline)"  };  #define I40E_TEST_LEN (sizeof(i40e_gstrings_test) / ETH_GSTRING_LEN) -static const char i40e_priv_flags_strings_gl[][ETH_GSTRING_LEN] = { +static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {  	"MFP",  	"LinkPolling",  	"flow-director-atr",  	"veb-stats",  	"hw-atr-eviction", -	"vf-true-promisc-support",  }; -#define I40E_PRIV_FLAGS_GL_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings_gl) +#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings) -static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = { -	"NPAR", -	"LinkPolling", -	"flow-director-atr", -	"veb-stats", -	"hw-atr-eviction", +/* Private flags with a global effect, restricted to PF 0 */ +static const char i40e_gl_priv_flags_strings[][ETH_GSTRING_LEN] = { +	"vf-true-promisc-support",  }; -#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings) +#define I40E_GL_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gl_priv_flags_strings)  /**   * i40e_partition_setting_complaint - generic complaint for MFP restriction @@ -271,8 +265,9 @@ static void i40e_partition_setting_complaint(struct i40e_pf *pf)  static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,  				     u32 *advertising)  { -	enum i40e_aq_capabilities_phy_type phy_types = pf->hw.phy.phy_types;  	struct i40e_link_status *hw_link_info = &pf->hw.phy.link_info; +	u64 phy_types = pf->hw.phy.phy_types; +  	*supported = 0x0;  	*advertising = 0x0; @@ -351,11 +346,13 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,  			*advertising |= ADVERTISED_20000baseKR2_Full;  	}  	if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) { -		*supported |= SUPPORTED_10000baseKR_Full | -			      SUPPORTED_Autoneg; +		if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER)) +			*supported |= SUPPORTED_10000baseKR_Full | +				      SUPPORTED_Autoneg;  		*advertising |= ADVERTISED_Autoneg;  		if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) -			*advertising |= ADVERTISED_10000baseKR_Full; +			if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER)) +				*advertising |= ADVERTISED_10000baseKR_Full;  	}  	if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) {  		*supported |= SUPPORTED_10000baseKX4_Full | @@ -365,11 +362,20 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,  			*advertising |= ADVERTISED_10000baseKX4_Full;  	}  	if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) { -		*supported |= SUPPORTED_1000baseKX_Full | -			      SUPPORTED_Autoneg; +		if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER)) +			*supported |= SUPPORTED_1000baseKX_Full | +				      SUPPORTED_Autoneg;  		*advertising |= ADVERTISED_Autoneg;  		if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) -			*advertising |= ADVERTISED_1000baseKX_Full; +			if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER)) +				*advertising |= ADVERTISED_1000baseKX_Full; +	} +	if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR || +	    phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR || +	    phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR || +	    phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR) { +		*supported |= SUPPORTED_Autoneg; +		*advertising |= ADVERTISED_Autoneg;  	}  } @@ -493,6 +499,14 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,  				     ADVERTISED_1000baseKX_Full |  				     ADVERTISED_Autoneg;  		break; +	case I40E_PHY_TYPE_25GBASE_KR: +	case I40E_PHY_TYPE_25GBASE_CR: +	case I40E_PHY_TYPE_25GBASE_SR: +	case I40E_PHY_TYPE_25GBASE_LR: +		ecmd->supported = SUPPORTED_Autoneg; +		ecmd->advertising = ADVERTISED_Autoneg; +		/* TODO: add speeds when ethtool is ready to support*/ +		break;  	default:  		/* if we got here and link is up something bad is afoot */  		netdev_info(netdev, "WARNING: Link is up but PHY type 0x%x is not recognized.\n", @@ -514,6 +528,14 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,  	case I40E_LINK_SPEED_40GB:  		ethtool_cmd_speed_set(ecmd, SPEED_40000);  		break; +	case I40E_LINK_SPEED_25GB: +#ifdef SPEED_25000 +		ethtool_cmd_speed_set(ecmd, SPEED_25000); +#else +		netdev_info(netdev, +			    "Speed is 25G, display not supported by this version of ethtool.\n"); +#endif +		break;  	case I40E_LINK_SPEED_20GB:  		ethtool_cmd_speed_set(ecmd, SPEED_20000);  		break; @@ -978,6 +1000,10 @@ static u32 i40e_get_msglevel(struct net_device *netdev)  {  	struct i40e_netdev_priv *np = netdev_priv(netdev);  	struct i40e_pf *pf = np->vsi->back; +	u32 debug_mask = pf->hw.debug_mask; + +	if (debug_mask) +		netdev_info(netdev, "i40e debug_mask: 0x%08X\n", debug_mask);  	return pf->msg_enable;  } @@ -989,7 +1015,8 @@ static void i40e_set_msglevel(struct net_device *netdev, u32 data)  	if (I40E_DEBUG_USER & data)  		pf->hw.debug_mask = data; -	pf->msg_enable = data; +	else +		pf->msg_enable = data;  }  static int i40e_get_regs_len(struct net_device *netdev) @@ -1191,10 +1218,9 @@ static void i40e_get_drvinfo(struct net_device *netdev,  		sizeof(drvinfo->fw_version));  	strlcpy(drvinfo->bus_info, pci_name(pf->pdev),  		sizeof(drvinfo->bus_info)); +	drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN;  	if (pf->hw.pf_id == 0) -		drvinfo->n_priv_flags = I40E_PRIV_FLAGS_GL_STR_LEN; -	else -		drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN; +		drvinfo->n_priv_flags += I40E_GL_PRIV_FLAGS_STR_LEN;  }  static void i40e_get_ringparam(struct net_device *netdev, @@ -1219,6 +1245,7 @@ static int i40e_set_ringparam(struct net_device *netdev,  {  	struct i40e_ring *tx_rings = NULL, *rx_rings = NULL;  	struct i40e_netdev_priv *np = netdev_priv(netdev); +	struct i40e_hw *hw = &np->vsi->back->hw;  	struct i40e_vsi *vsi = np->vsi;  	struct i40e_pf *pf = vsi->back;  	u32 new_rx_count, new_tx_count; @@ -1311,10 +1338,6 @@ static int i40e_set_ringparam(struct net_device *netdev,  		}  		for (i = 0; i < vsi->num_queue_pairs; i++) { -			/* this is to allow wr32 to have something to write to -			 * during early allocation of Rx buffers -			 */ -			u32 __iomem faketail = 0;  			struct i40e_ring *ring;  			u16 unused; @@ -1326,7 +1349,10 @@ static int i40e_set_ringparam(struct net_device *netdev,  			 */  			rx_rings[i].desc = NULL;  			rx_rings[i].rx_bi = NULL; -			rx_rings[i].tail = (u8 __iomem *)&faketail; +			/* this is to allow wr32 to have something to write to +			 * during early allocation of Rx buffers +			 */ +			rx_rings[i].tail = hw->hw_addr + I40E_PRTGEN_STATUS;  			err = i40e_setup_rx_descriptors(&rx_rings[i]);  			if (err)  				goto rx_unwind; @@ -1422,10 +1448,8 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)  			return I40E_VSI_STATS_LEN(netdev);  		}  	case ETH_SS_PRIV_FLAGS: -		if (pf->hw.pf_id == 0) -			return I40E_PRIV_FLAGS_GL_STR_LEN; -		else -			return I40E_PRIV_FLAGS_STR_LEN; +		return I40E_PRIV_FLAGS_STR_LEN + +			(pf->hw.pf_id == 0 ? I40E_GL_PRIV_FLAGS_STR_LEN : 0);  	default:  		return -EOPNOTSUPP;  	} @@ -1536,10 +1560,8 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,  	switch (stringset) {  	case ETH_SS_TEST: -		for (i = 0; i < I40E_TEST_LEN; i++) { -			memcpy(data, i40e_gstrings_test[i], ETH_GSTRING_LEN); -			data += ETH_GSTRING_LEN; -		} +		memcpy(data, i40e_gstrings_test, +		       I40E_TEST_LEN * ETH_GSTRING_LEN);  		break;  	case ETH_SS_STATS:  		for (i = 0; i < I40E_NETDEV_STATS_LEN; i++) { @@ -1623,19 +1645,12 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,  		/* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */  		break;  	case ETH_SS_PRIV_FLAGS: -		if (pf->hw.pf_id == 0) { -			for (i = 0; i < I40E_PRIV_FLAGS_GL_STR_LEN; i++) { -				memcpy(data, i40e_priv_flags_strings_gl[i], -				       ETH_GSTRING_LEN); -				data += ETH_GSTRING_LEN; -			} -		} else { -			for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) { -				memcpy(data, i40e_priv_flags_strings[i], -				       ETH_GSTRING_LEN); -				data += ETH_GSTRING_LEN; -			} -		} +		memcpy(data, i40e_priv_flags_strings, +		       I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN); +		data += I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN; +		if (pf->hw.pf_id == 0) +			memcpy(data, i40e_gl_priv_flags_strings, +			       I40E_GL_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);  		break;  	default:  		break; @@ -1666,8 +1681,19 @@ static int i40e_get_ts_info(struct net_device *dev,  	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);  	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | -			   BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT) | -			   BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); +			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | +			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | +			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ); + +	if (pf->flags & I40E_FLAG_PTP_L4_CAPABLE) +		info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | +				    BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | +				    BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | +				    BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | +				    BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) | +				    BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | +				    BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | +				    BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);  	return 0;  } @@ -1739,17 +1765,6 @@ static int i40e_intr_test(struct net_device *netdev, u64 *data)  	return *data;  } -static int i40e_loopback_test(struct net_device *netdev, u64 *data) -{ -	struct i40e_netdev_priv *np = netdev_priv(netdev); -	struct i40e_pf *pf = np->vsi->back; - -	netif_info(pf, hw, netdev, "loopback test not implemented\n"); -	*data = 0; - -	return *data; -} -  static inline bool i40e_active_vfs(struct i40e_pf *pf)  {  	struct i40e_vf *vfs = pf->vf; @@ -1763,17 +1778,7 @@ static inline bool i40e_active_vfs(struct i40e_pf *pf)  static inline bool i40e_active_vmdqs(struct i40e_pf *pf)  { -	struct i40e_vsi **vsi = pf->vsi; -	int i; - -	for (i = 0; i < pf->num_alloc_vsi; i++) { -		if (!vsi[i]) -			continue; -		if (vsi[i]->type == I40E_VSI_VMDQ2) -			return true; -	} - -	return false; +	return !!i40e_find_vsi_by_type(pf, I40E_VSI_VMDQ2);  }  static void i40e_diag_test(struct net_device *netdev, @@ -1795,7 +1800,6 @@ static void i40e_diag_test(struct net_device *netdev,  			data[I40E_ETH_TEST_REG]		= 1;  			data[I40E_ETH_TEST_EEPROM]	= 1;  			data[I40E_ETH_TEST_INTR]	= 1; -			data[I40E_ETH_TEST_LOOPBACK]	= 1;  			data[I40E_ETH_TEST_LINK]	= 1;  			eth_test->flags |= ETH_TEST_FL_FAILED;  			clear_bit(__I40E_TESTING, &pf->state); @@ -1823,9 +1827,6 @@ static void i40e_diag_test(struct net_device *netdev,  		if (i40e_intr_test(netdev, &data[I40E_ETH_TEST_INTR]))  			eth_test->flags |= ETH_TEST_FL_FAILED; -		if (i40e_loopback_test(netdev, &data[I40E_ETH_TEST_LOOPBACK])) -			eth_test->flags |= ETH_TEST_FL_FAILED; -  		/* run reg test last, a reset is required after it */  		if (i40e_reg_test(netdev, &data[I40E_ETH_TEST_REG]))  			eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1846,7 +1847,6 @@ static void i40e_diag_test(struct net_device *netdev,  		data[I40E_ETH_TEST_REG] = 0;  		data[I40E_ETH_TEST_EEPROM] = 0;  		data[I40E_ETH_TEST_INTR] = 0; -		data[I40E_ETH_TEST_LOOPBACK] = 0;  	}  skip_ol_tests: @@ -1925,7 +1925,7 @@ static int i40e_set_phys_id(struct net_device *netdev,  	switch (state) {  	case ETHTOOL_ID_ACTIVE: -		if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY)) { +		if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS)) {  			pf->led_status = i40e_led_get(hw);  		} else {  			i40e_aq_set_phy_debug(hw, I40E_PHY_DEBUG_ALL, NULL); @@ -1935,20 +1935,20 @@ static int i40e_set_phys_id(struct net_device *netdev,  		}  		return blink_freq;  	case ETHTOOL_ID_ON: -		if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY)) +		if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))  			i40e_led_set(hw, 0xf, false);  		else  			ret = i40e_led_set_phy(hw, true, pf->led_status, 0);  		break;  	case ETHTOOL_ID_OFF: -		if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY)) +		if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))  			i40e_led_set(hw, 0x0, false);  		else  			ret = i40e_led_set_phy(hw, false, pf->led_status, 0);  		break;  	case ETHTOOL_ID_INACTIVE: -		if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY)) { -			i40e_led_set(hw, false, pf->led_status); +		if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS)) { +			i40e_led_set(hw, pf->led_status, false);  		} else {  			ret = i40e_led_set_phy(hw, false, pf->led_status,  					       (pf->phy_led_val | diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 58e6c1570335..b077ef8b00fa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -1522,12 +1522,12 @@ void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi)  	 * same PCI function.  	 */  	netdev->dev_port = 1; -	spin_lock_bh(&vsi->mac_filter_list_lock); -	i40e_add_filter(vsi, hw->mac.san_addr, 0, false, false); -	i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false); -	i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false); -	i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false); -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	spin_lock_bh(&vsi->mac_filter_hash_lock); +	i40e_add_filter(vsi, hw->mac.san_addr, 0); +	i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0); +	i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0); +	i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0); +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	/* use san mac */  	ether_addr_copy(netdev->dev_addr, hw->mac.san_addr); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 31c97e3937a4..ad4cf639430e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -41,7 +41,7 @@ static const char i40e_driver_string[] =  #define DRV_VERSION_MAJOR 1  #define DRV_VERSION_MINOR 6 -#define DRV_VERSION_BUILD 16 +#define DRV_VERSION_BUILD 25  #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \  	     __stringify(DRV_VERSION_MINOR) "." \  	     __stringify(DRV_VERSION_BUILD)    DRV_KERN @@ -86,6 +86,8 @@ static const struct pci_device_id i40e_pci_tbl[] = {  	{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_I_X722), 0},  	{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0},  	{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2_A), 0}, +	{PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_B), 0}, +	{PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_SFP28), 0},  	/* required last entry */  	{0, }  }; @@ -93,8 +95,8 @@ MODULE_DEVICE_TABLE(pci, i40e_pci_tbl);  #define I40E_MAX_VF_COUNT 128  static int debug = -1; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); +module_param(debug, uint, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX)");  MODULE_AUTHOR("Intel Corporation, <[email protected]>");  MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver"); @@ -286,8 +288,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)  void i40e_service_event_schedule(struct i40e_pf *pf)  {  	if (!test_bit(__I40E_DOWN, &pf->state) && -	    !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) && -	    !test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state)) +	    !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))  		queue_work(i40e_wq, &pf->service_task);  } @@ -1145,25 +1146,22 @@ void i40e_update_stats(struct i40e_vsi *vsi)   * @vsi: the VSI to be searched   * @macaddr: the MAC address   * @vlan: the vlan - * @is_vf: make sure its a VF filter, else doesn't matter - * @is_netdev: make sure its a netdev filter, else doesn't matter   *   * Returns ptr to the filter object or NULL   **/  static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi, -						u8 *macaddr, s16 vlan, -						bool is_vf, bool is_netdev) +						const u8 *macaddr, s16 vlan)  {  	struct i40e_mac_filter *f; +	u64 key;  	if (!vsi || !macaddr)  		return NULL; -	list_for_each_entry(f, &vsi->mac_filter_list, list) { +	key = i40e_addr_to_hkey(macaddr); +	hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) {  		if ((ether_addr_equal(macaddr, f->macaddr)) && -		    (vlan == f->vlan)    && -		    (!is_vf || f->is_vf) && -		    (!is_netdev || f->is_netdev)) +		    (vlan == f->vlan))  			return f;  	}  	return NULL; @@ -1173,24 +1171,21 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,   * i40e_find_mac - Find a mac addr in the macvlan filters list   * @vsi: the VSI to be searched   * @macaddr: the MAC address we are searching for - * @is_vf: make sure its a VF filter, else doesn't matter - * @is_netdev: make sure its a netdev filter, else doesn't matter   *   * Returns the first filter with the provided MAC address or NULL if   * MAC address was not found   **/ -struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, -				      bool is_vf, bool is_netdev) +struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr)  {  	struct i40e_mac_filter *f; +	u64 key;  	if (!vsi || !macaddr)  		return NULL; -	list_for_each_entry(f, &vsi->mac_filter_list, list) { -		if ((ether_addr_equal(macaddr, f->macaddr)) && -		    (!is_vf || f->is_vf) && -		    (!is_netdev || f->is_netdev)) +	key = i40e_addr_to_hkey(macaddr); +	hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) { +		if ((ether_addr_equal(macaddr, f->macaddr)))  			return f;  	}  	return NULL; @@ -1204,86 +1199,132 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,   **/  bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi)  { -	struct i40e_mac_filter *f; +	/* If we have a PVID, always operate in VLAN mode */ +	if (vsi->info.pvid) +		return true; -	/* Only -1 for all the filters denotes not in vlan mode -	 * so we have to go through all the list in order to make sure +	/* We need to operate in VLAN mode whenever we have any filters with +	 * a VLAN other than I40E_VLAN_ALL. We could check the table each +	 * time, incurring search cost repeatedly. However, we can notice two +	 * things: +	 * +	 * 1) the only place where we can gain a VLAN filter is in +	 *    i40e_add_filter. +	 * +	 * 2) the only place where filters are actually removed is in +	 *    i40e_sync_filters_subtask. +	 * +	 * Thus, we can simply use a boolean value, has_vlan_filters which we +	 * will set to true when we add a VLAN filter in i40e_add_filter. Then +	 * we have to perform the full search after deleting filters in +	 * i40e_sync_filters_subtask, but we already have to search +	 * filters here and can perform the check at the same time. This +	 * results in avoiding embedding a loop for VLAN mode inside another +	 * loop over all the filters, and should maintain correctness as noted +	 * above.  	 */ -	list_for_each_entry(f, &vsi->mac_filter_list, list) { -		if (f->vlan >= 0 || vsi->info.pvid) -			return true; -	} - -	return false; +	return vsi->has_vlan_filter;  }  /** - * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans - * @vsi: the VSI to be searched - * @macaddr: the mac address to be filtered - * @is_vf: true if it is a VF - * @is_netdev: true if it is a netdev + * i40e_correct_mac_vlan_filters - Correct non-VLAN filters if necessary + * @vsi: the VSI to configure + * @tmp_add_list: list of filters ready to be added + * @tmp_del_list: list of filters ready to be deleted + * @vlan_filters: the number of active VLAN filters   * - * Goes through all the macvlan filters and adds a - * macvlan filter for each unique vlan that already exists + * Update VLAN=0 and VLAN=-1 (I40E_VLAN_ANY) filters properly so that they + * behave as expected. If we have any active VLAN filters remaining or about + * to be added then we need to update non-VLAN filters to be marked as VLAN=0 + * so that they only match against untagged traffic. If we no longer have any + * active VLAN filters, we need to make all non-VLAN filters marked as VLAN=-1 + * so that they match against both tagged and untagged traffic. In this way, + * we ensure that we correctly receive the desired traffic. This ensures that + * when we have an active VLAN we will receive only untagged traffic and + * traffic matching active VLANs. If we have no active VLANs then we will + * operate in non-VLAN mode and receive all traffic, tagged or untagged.   * - * Returns first filter found on success, else NULL - **/ -struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr, -					     bool is_vf, bool is_netdev) + * Finally, in a similar fashion, this function also corrects filters when + * there is an active PVID assigned to this VSI. + * + * In case of memory allocation failure return -ENOMEM. Otherwise, return 0. + * + * This function is only expected to be called from within + * i40e_sync_vsi_filters. + * + * NOTE: This function expects to be called while under the + * mac_filter_hash_lock + */ +static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi, +					 struct hlist_head *tmp_add_list, +					 struct hlist_head *tmp_del_list, +					 int vlan_filters)  { -	struct i40e_mac_filter *f; +	struct i40e_mac_filter *f, *add_head; +	struct hlist_node *h; +	int bkt, new_vlan; -	list_for_each_entry(f, &vsi->mac_filter_list, list) { -		if (vsi->info.pvid) -			f->vlan = le16_to_cpu(vsi->info.pvid); -		if (!i40e_find_filter(vsi, macaddr, f->vlan, -				      is_vf, is_netdev)) { -			if (!i40e_add_filter(vsi, macaddr, f->vlan, -					     is_vf, is_netdev)) -				return NULL; -		} -	} +	/* To determine if a particular filter needs to be replaced we +	 * have the three following conditions: +	 * +	 * a) if we have a PVID assigned, then all filters which are +	 *    not marked as VLAN=PVID must be replaced with filters that +	 *    are. +	 * b) otherwise, if we have any active VLANS, all filters +	 *    which are marked as VLAN=-1 must be replaced with +	 *    filters marked as VLAN=0 +	 * c) finally, if we do not have any active VLANS, all filters +	 *    which are marked as VLAN=0 must be replaced with filters +	 *    marked as VLAN=-1 +	 */ -	return list_first_entry_or_null(&vsi->mac_filter_list, -					struct i40e_mac_filter, list); -} +	/* Update the filters about to be added in place */ +	hlist_for_each_entry(f, tmp_add_list, hlist) { +		if (vsi->info.pvid && f->vlan != vsi->info.pvid) +			f->vlan = vsi->info.pvid; +		else if (vlan_filters && f->vlan == I40E_VLAN_ANY) +			f->vlan = 0; +		else if (!vlan_filters && f->vlan == 0) +			f->vlan = I40E_VLAN_ANY; +	} + +	/* Update the remaining active filters */ +	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { +		/* Combine the checks for whether a filter needs to be changed +		 * and then determine the new VLAN inside the if block, in +		 * order to avoid duplicating code for adding the new filter +		 * then deleting the old filter. +		 */ +		if ((vsi->info.pvid && f->vlan != vsi->info.pvid) || +		    (vlan_filters && f->vlan == I40E_VLAN_ANY) || +		    (!vlan_filters && f->vlan == 0)) { +			/* Determine the new vlan we will be adding */ +			if (vsi->info.pvid) +				new_vlan = vsi->info.pvid; +			else if (vlan_filters) +				new_vlan = 0; +			else +				new_vlan = I40E_VLAN_ANY; -/** - * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS - * @vsi: the VSI to be searched - * @macaddr: the mac address to be removed - * @is_vf: true if it is a VF - * @is_netdev: true if it is a netdev - * - * Removes a given MAC address from a VSI, regardless of VLAN - * - * Returns 0 for success, or error - **/ -int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr, -			  bool is_vf, bool is_netdev) -{ -	struct i40e_mac_filter *f = NULL; -	int changed = 0; +			/* Create the new filter */ +			add_head = i40e_add_filter(vsi, f->macaddr, new_vlan); +			if (!add_head) +				return -ENOMEM; -	WARN(!spin_is_locked(&vsi->mac_filter_list_lock), -	     "Missing mac_filter_list_lock\n"); -	list_for_each_entry(f, &vsi->mac_filter_list, list) { -		if ((ether_addr_equal(macaddr, f->macaddr)) && -		    (is_vf == f->is_vf) && -		    (is_netdev == f->is_netdev)) { -			f->counter--; -			changed = 1; -			if (f->counter == 0) -				f->state = I40E_FILTER_REMOVE; +			/* Put the replacement filter into the add list */ +			hash_del(&add_head->hlist); +			hlist_add_head(&add_head->hlist, tmp_add_list); + +			/* Put the original filter into the delete list */ +			f->state = I40E_FILTER_REMOVE; +			hash_del(&f->hlist); +			hlist_add_head(&f->hlist, tmp_del_list);  		}  	} -	if (changed) { -		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; -		vsi->back->flags |= I40E_FLAG_FILTER_SYNC; -		return 0; -	} -	return -ENOENT; + +	vsi->has_vlan_filter = !!vlan_filters; + +	return 0;  }  /** @@ -1324,36 +1365,32 @@ static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)   * @vsi: the VSI to be searched   * @macaddr: the MAC address   * @vlan: the vlan - * @is_vf: make sure its a VF filter, else doesn't matter - * @is_netdev: make sure its a netdev filter, else doesn't matter   *   * Returns ptr to the filter object or NULL when no memory available.   * - * NOTE: This function is expected to be called with mac_filter_list_lock + * NOTE: This function is expected to be called with mac_filter_hash_lock   * being held.   **/  struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, -					u8 *macaddr, s16 vlan, -					bool is_vf, bool is_netdev) +					const u8 *macaddr, s16 vlan)  {  	struct i40e_mac_filter *f; -	int changed = false; +	u64 key;  	if (!vsi || !macaddr)  		return NULL; -	/* Do not allow broadcast filter to be added since broadcast filter -	 * is added as part of add VSI for any newly created VSI except -	 * FDIR VSI -	 */ -	if (is_broadcast_ether_addr(macaddr)) -		return NULL; - -	f = i40e_find_filter(vsi, macaddr, vlan, is_vf, is_netdev); +	f = i40e_find_filter(vsi, macaddr, vlan);  	if (!f) {  		f = kzalloc(sizeof(*f), GFP_ATOMIC);  		if (!f) -			goto add_filter_out; +			return NULL; + +		/* Update the boolean indicating if we need to function in +		 * VLAN mode. +		 */ +		if (vlan >= 0) +			vsi->has_vlan_filter = true;  		ether_addr_copy(f->macaddr, macaddr);  		f->vlan = vlan; @@ -1365,100 +1402,148 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,  			f->state = I40E_FILTER_FAILED;  		else  			f->state = I40E_FILTER_NEW; -		changed = true; -		INIT_LIST_HEAD(&f->list); -		list_add_tail(&f->list, &vsi->mac_filter_list); -	} +		INIT_HLIST_NODE(&f->hlist); -	/* increment counter and add a new flag if needed */ -	if (is_vf) { -		if (!f->is_vf) { -			f->is_vf = true; -			f->counter++; -		} -	} else if (is_netdev) { -		if (!f->is_netdev) { -			f->is_netdev = true; -			f->counter++; -		} -	} else { -		f->counter++; -	} +		key = i40e_addr_to_hkey(macaddr); +		hash_add(vsi->mac_filter_hash, &f->hlist, key); -	if (changed) {  		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;  		vsi->back->flags |= I40E_FLAG_FILTER_SYNC;  	} -add_filter_out: +	/* If we're asked to add a filter that has been marked for removal, it +	 * is safe to simply restore it to active state. __i40e_del_filter +	 * will have simply deleted any filters which were previously marked +	 * NEW or FAILED, so if it is currently marked REMOVE it must have +	 * previously been ACTIVE. Since we haven't yet run the sync filters +	 * task, just restore this filter to the ACTIVE state so that the +	 * sync task leaves it in place +	 */ +	if (f->state == I40E_FILTER_REMOVE) +		f->state = I40E_FILTER_ACTIVE; +  	return f;  }  /** - * i40e_del_filter - Remove a mac/vlan filter from the VSI + * __i40e_del_filter - Remove a specific filter from the VSI + * @vsi: VSI to remove from + * @f: the filter to remove from the list + * + * This function should be called instead of i40e_del_filter only if you know + * the exact filter you will remove already, such as via i40e_find_filter or + * i40e_find_mac. + * + * NOTE: This function is expected to be called with mac_filter_hash_lock + * being held. + * ANOTHER NOTE: This function MUST be called from within the context of + * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe() + * instead of list_for_each_entry(). + **/ +static void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f) +{ +	if (!f) +		return; + +	if ((f->state == I40E_FILTER_FAILED) || +	    (f->state == I40E_FILTER_NEW)) { +		/* this one never got added by the FW. Just remove it, +		 * no need to sync anything. +		 */ +		hash_del(&f->hlist); +		kfree(f); +	} else { +		f->state = I40E_FILTER_REMOVE; +		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; +		vsi->back->flags |= I40E_FLAG_FILTER_SYNC; +	} +} + +/** + * i40e_del_filter - Remove a MAC/VLAN filter from the VSI   * @vsi: the VSI to be searched   * @macaddr: the MAC address - * @vlan: the vlan - * @is_vf: make sure it's a VF filter, else doesn't matter - * @is_netdev: make sure it's a netdev filter, else doesn't matter + * @vlan: the VLAN   * - * NOTE: This function is expected to be called with mac_filter_list_lock + * NOTE: This function is expected to be called with mac_filter_hash_lock   * being held.   * ANOTHER NOTE: This function MUST be called from within the context of   * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()   * instead of list_for_each_entry().   **/ -void i40e_del_filter(struct i40e_vsi *vsi, -		     u8 *macaddr, s16 vlan, -		     bool is_vf, bool is_netdev) +void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)  {  	struct i40e_mac_filter *f;  	if (!vsi || !macaddr)  		return; -	f = i40e_find_filter(vsi, macaddr, vlan, is_vf, is_netdev); -	if (!f || f->counter == 0) -		return; +	f = i40e_find_filter(vsi, macaddr, vlan); +	__i40e_del_filter(vsi, f); +} -	if (is_vf) { -		if (f->is_vf) { -			f->is_vf = false; -			f->counter--; -		} -	} else if (is_netdev) { -		if (f->is_netdev) { -			f->is_netdev = false; -			f->counter--; -		} -	} else { -		/* make sure we don't remove a filter in use by VF or netdev */ -		int min_f = 0; +/** + * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans + * @vsi: the VSI to be searched + * @macaddr: the mac address to be filtered + * + * Goes through all the macvlan filters and adds a macvlan filter for each + * unique vlan that already exists. If a PVID has been assigned, instead only + * add the macaddr to that VLAN. + * + * Returns last filter added on success, else NULL + **/ +struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, +					     const u8 *macaddr) +{ +	struct i40e_mac_filter *f, *add = NULL; +	struct hlist_node *h; +	int bkt; -		min_f += (f->is_vf ? 1 : 0); -		min_f += (f->is_netdev ? 1 : 0); +	if (vsi->info.pvid) +		return i40e_add_filter(vsi, macaddr, +				       le16_to_cpu(vsi->info.pvid)); -		if (f->counter > min_f) -			f->counter--; +	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { +		if (f->state == I40E_FILTER_REMOVE) +			continue; +		add = i40e_add_filter(vsi, macaddr, f->vlan); +		if (!add) +			return NULL;  	} -	/* counter == 0 tells sync_filters_subtask to -	 * remove the filter from the firmware's list -	 */ -	if (f->counter == 0) { -		if ((f->state == I40E_FILTER_FAILED) || -		    (f->state == I40E_FILTER_NEW)) { -			/* this one never got added by the FW. Just remove it, -			 * no need to sync anything. -			 */ -			list_del(&f->list); -			kfree(f); -		} else { -			f->state = I40E_FILTER_REMOVE; -			vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; -			vsi->back->flags |= I40E_FLAG_FILTER_SYNC; +	return add; +} + +/** + * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS + * @vsi: the VSI to be searched + * @macaddr: the mac address to be removed + * + * Removes a given MAC address from a VSI, regardless of VLAN + * + * Returns 0 for success, or error + **/ +int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr) +{ +	struct i40e_mac_filter *f; +	struct hlist_node *h; +	bool found = false; +	int bkt; + +	WARN(!spin_is_locked(&vsi->mac_filter_hash_lock), +	     "Missing mac_filter_hash_lock\n"); +	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { +		if (ether_addr_equal(macaddr, f->macaddr)) { +			__i40e_del_filter(vsi, f); +			found = true;  		}  	} + +	if (found) +		return 0; +	else +		return -ENOENT;  }  /** @@ -1499,10 +1584,10 @@ static int i40e_set_mac(struct net_device *netdev, void *p)  	else  		netdev_info(netdev, "set new mac address %pM\n", addr->sa_data); -	spin_lock_bh(&vsi->mac_filter_list_lock); -	i40e_del_mac_all_vlan(vsi, netdev->dev_addr, false, true); -	i40e_put_mac_in_vlan(vsi, addr->sa_data, false, true); -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	spin_lock_bh(&vsi->mac_filter_hash_lock); +	i40e_del_mac_all_vlan(vsi, netdev->dev_addr); +	i40e_put_mac_in_vlan(vsi, addr->sa_data); +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	ether_addr_copy(netdev->dev_addr, addr->sa_data);  	if (vsi->type == I40E_VSI_MAIN) {  		i40e_status ret; @@ -1666,6 +1751,52 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,  }  /** + * i40e_addr_sync - Callback for dev_(mc|uc)_sync to add address + * @netdev: the netdevice + * @addr: address to add + * + * Called by __dev_(mc|uc)_sync when an address needs to be added. We call + * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock. + */ +static int i40e_addr_sync(struct net_device *netdev, const u8 *addr) +{ +	struct i40e_netdev_priv *np = netdev_priv(netdev); +	struct i40e_vsi *vsi = np->vsi; +	struct i40e_mac_filter *f; + +	if (i40e_is_vsi_in_vlan(vsi)) +		f = i40e_put_mac_in_vlan(vsi, addr); +	else +		f = i40e_add_filter(vsi, addr, I40E_VLAN_ANY); + +	if (f) +		return 0; +	else +		return -ENOMEM; +} + +/** + * i40e_addr_unsync - Callback for dev_(mc|uc)_sync to remove address + * @netdev: the netdevice + * @addr: address to add + * + * Called by __dev_(mc|uc)_sync when an address needs to be removed. We call + * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock. + */ +static int i40e_addr_unsync(struct net_device *netdev, const u8 *addr) +{ +	struct i40e_netdev_priv *np = netdev_priv(netdev); +	struct i40e_vsi *vsi = np->vsi; + +	if (i40e_is_vsi_in_vlan(vsi)) +		i40e_del_mac_all_vlan(vsi, addr); +	else +		i40e_del_filter(vsi, addr, I40E_VLAN_ANY); + +	return 0; +} + +/**   * i40e_set_rx_mode - NDO callback to set the netdev filters   * @netdev: network interface device structure   **/ @@ -1676,62 +1807,14 @@ static void i40e_set_rx_mode(struct net_device *netdev)  #endif  {  	struct i40e_netdev_priv *np = netdev_priv(netdev); -	struct i40e_mac_filter *f, *ftmp;  	struct i40e_vsi *vsi = np->vsi; -	struct netdev_hw_addr *uca; -	struct netdev_hw_addr *mca; -	struct netdev_hw_addr *ha; - -	spin_lock_bh(&vsi->mac_filter_list_lock); - -	/* add addr if not already in the filter list */ -	netdev_for_each_uc_addr(uca, netdev) { -		if (!i40e_find_mac(vsi, uca->addr, false, true)) { -			if (i40e_is_vsi_in_vlan(vsi)) -				i40e_put_mac_in_vlan(vsi, uca->addr, -						     false, true); -			else -				i40e_add_filter(vsi, uca->addr, I40E_VLAN_ANY, -						false, true); -		} -	} -	netdev_for_each_mc_addr(mca, netdev) { -		if (!i40e_find_mac(vsi, mca->addr, false, true)) { -			if (i40e_is_vsi_in_vlan(vsi)) -				i40e_put_mac_in_vlan(vsi, mca->addr, -						     false, true); -			else -				i40e_add_filter(vsi, mca->addr, I40E_VLAN_ANY, -						false, true); -		} -	} - -	/* remove filter if not in netdev list */ -	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { - -		if (!f->is_netdev) -			continue; +	spin_lock_bh(&vsi->mac_filter_hash_lock); -		netdev_for_each_mc_addr(mca, netdev) -			if (ether_addr_equal(mca->addr, f->macaddr)) -				goto bottom_of_search_loop; +	__dev_uc_sync(netdev, i40e_addr_sync, i40e_addr_unsync); +	__dev_mc_sync(netdev, i40e_addr_sync, i40e_addr_unsync); -		netdev_for_each_uc_addr(uca, netdev) -			if (ether_addr_equal(uca->addr, f->macaddr)) -				goto bottom_of_search_loop; - -		for_each_dev_addr(netdev, ha) -			if (ether_addr_equal(ha->addr, f->macaddr)) -				goto bottom_of_search_loop; - -		/* f->macaddr wasn't found in uc, mc, or ha list so delete it */ -		i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY, false, true); - -bottom_of_search_loop: -		continue; -	} -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	/* check for other flag changes */  	if (vsi->current_netdev_flags != vsi->netdev->flags) { @@ -1746,21 +1829,26 @@ bottom_of_search_loop:  }  /** - * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries - * @vsi: pointer to vsi struct + * i40e_undo_filter_entries - Undo the changes made to MAC filter entries + * @vsi: Pointer to VSI struct   * @from: Pointer to list which contains MAC filter entries - changes to   *        those entries needs to be undone.   * - * MAC filter entries from list were slated to be removed from device. + * MAC filter entries from list were slated to be sent to firmware, either for + * addition or deletion.   **/ -static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi, -					 struct list_head *from) +static void i40e_undo_filter_entries(struct i40e_vsi *vsi, +				     struct hlist_head *from)  { -	struct i40e_mac_filter *f, *ftmp; +	struct i40e_mac_filter *f; +	struct hlist_node *h; + +	hlist_for_each_entry_safe(f, h, from, hlist) { +		u64 key = i40e_addr_to_hkey(f->macaddr); -	list_for_each_entry_safe(f, ftmp, from, list) {  		/* Move the element back into MAC filter list*/ -		list_move_tail(&f->list, &vsi->mac_filter_list); +		hlist_del(&f->hlist); +		hash_add(vsi->mac_filter_hash, &f->hlist, key);  	}  } @@ -1770,7 +1858,6 @@ static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,   * @count: Number of filters added   * @add_list: return data from fw   * @head: pointer to first filter in current batch - * @aq_err: status from fw   *   * MAC filter entries from list were slated to be added to device. Returns   * number of successful filters. Note that 0 does NOT mean success! @@ -1778,45 +1865,146 @@ static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,  static int  i40e_update_filter_state(int count,  			 struct i40e_aqc_add_macvlan_element_data *add_list, -			 struct i40e_mac_filter *add_head, int aq_err) +			 struct i40e_mac_filter *add_head)  {  	int retval = 0;  	int i; - -	if (!aq_err) { -		retval = count; -		/* Everything's good, mark all filters active. */ -		for (i = 0; i < count ; i++) { -			add_head->state = I40E_FILTER_ACTIVE; -			add_head = list_next_entry(add_head, list); -		} -	} else if (aq_err == I40E_AQ_RC_ENOSPC) { -		/* Device ran out of filter space. Check the return value -		 * for each filter to see which ones are active. +	for (i = 0; i < count; i++) { +		/* Always check status of each filter. We don't need to check +		 * the firmware return status because we pre-set the filter +		 * status to I40E_AQC_MM_ERR_NO_RES when sending the filter +		 * request to the adminq. Thus, if it no longer matches then +		 * we know the filter is active.  		 */ -		for (i = 0; i < count ; i++) { -			if (add_list[i].match_method == -			    I40E_AQC_MM_ERR_NO_RES) { -				add_head->state = I40E_FILTER_FAILED; -			} else { -				add_head->state = I40E_FILTER_ACTIVE; -				retval++; -			} -			add_head = list_next_entry(add_head, list); -		} -	} else { -		/* Some other horrible thing happened, fail all filters */ -		retval = 0; -		for (i = 0; i < count ; i++) { +		if (add_list[i].match_method == I40E_AQC_MM_ERR_NO_RES) {  			add_head->state = I40E_FILTER_FAILED; -			add_head = list_next_entry(add_head, list); +		} else { +			add_head->state = I40E_FILTER_ACTIVE; +			retval++;  		} + +		add_head = hlist_entry(add_head->hlist.next, +				       typeof(struct i40e_mac_filter), +				       hlist);  	} +  	return retval;  }  /** + * i40e_aqc_del_filters - Request firmware to delete a set of filters + * @vsi: ptr to the VSI + * @vsi_name: name to display in messages + * @list: the list of filters to send to firmware + * @num_del: the number of filters to delete + * @retval: Set to -EIO on failure to delete + * + * Send a request to firmware via AdminQ to delete a set of filters. Uses + * *retval instead of a return value so that success does not force ret_val to + * be set to 0. This ensures that a sequence of calls to this function + * preserve the previous value of *retval on successful delete. + */ +static +void i40e_aqc_del_filters(struct i40e_vsi *vsi, const char *vsi_name, +			  struct i40e_aqc_remove_macvlan_element_data *list, +			  int num_del, int *retval) +{ +	struct i40e_hw *hw = &vsi->back->hw; +	i40e_status aq_ret; +	int aq_err; + +	aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, list, num_del, NULL); +	aq_err = hw->aq.asq_last_status; + +	/* Explicitly ignore and do not report when firmware returns ENOENT */ +	if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) { +		*retval = -EIO; +		dev_info(&vsi->back->pdev->dev, +			 "ignoring delete macvlan error on %s, err %s, aq_err %s\n", +			 vsi_name, i40e_stat_str(hw, aq_ret), +			 i40e_aq_str(hw, aq_err)); +	} +} + +/** + * i40e_aqc_add_filters - Request firmware to add a set of filters + * @vsi: ptr to the VSI + * @vsi_name: name to display in messages + * @list: the list of filters to send to firmware + * @add_head: Position in the add hlist + * @num_add: the number of filters to add + * @promisc_change: set to true on exit if promiscuous mode was forced on + * + * Send a request to firmware via AdminQ to add a chunk of filters. Will set + * promisc_changed to true if the firmware has run out of space for more + * filters. + */ +static +void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name, +			  struct i40e_aqc_add_macvlan_element_data *list, +			  struct i40e_mac_filter *add_head, +			  int num_add, bool *promisc_changed) +{ +	struct i40e_hw *hw = &vsi->back->hw; +	int aq_err, fcnt; + +	i40e_aq_add_macvlan(hw, vsi->seid, list, num_add, NULL); +	aq_err = hw->aq.asq_last_status; +	fcnt = i40e_update_filter_state(num_add, list, add_head); + +	if (fcnt != num_add) { +		*promisc_changed = true; +		set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state); +		dev_warn(&vsi->back->pdev->dev, +			 "Error %s adding RX filters on %s, promiscuous mode forced on\n", +			 i40e_aq_str(hw, aq_err), +			 vsi_name); +	} +} + +/** + * i40e_aqc_broadcast_filter - Set promiscuous broadcast flags + * @vsi: pointer to the VSI + * @f: filter data + * + * This function sets or clears the promiscuous broadcast flags for VLAN + * filters in order to properly receive broadcast frames. Assumes that only + * broadcast filters are passed. + **/ +static +void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name, +			       struct i40e_mac_filter *f) +{ +	bool enable = f->state == I40E_FILTER_NEW; +	struct i40e_hw *hw = &vsi->back->hw; +	i40e_status aq_ret; + +	if (f->vlan == I40E_VLAN_ANY) { +		aq_ret = i40e_aq_set_vsi_broadcast(hw, +						   vsi->seid, +						   enable, +						   NULL); +	} else { +		aq_ret = i40e_aq_set_vsi_bc_promisc_on_vlan(hw, +							    vsi->seid, +							    enable, +							    f->vlan, +							    NULL); +	} + +	if (aq_ret) { +		dev_warn(&vsi->back->pdev->dev, +			 "Error %s setting broadcast promiscuous mode on %s\n", +			 i40e_aq_str(hw, hw->aq.asq_last_status), +			 vsi_name); +		f->state = I40E_FILTER_FAILED; +	} else if (enable) { +		f->state = I40E_FILTER_ACTIVE; +	} +} + +/**   * i40e_sync_vsi_filters - Update the VSI filter list to the HW   * @vsi: ptr to the VSI   * @@ -1826,22 +2014,24 @@ i40e_update_filter_state(int count,   **/  int i40e_sync_vsi_filters(struct i40e_vsi *vsi)  { -	struct i40e_mac_filter *f, *ftmp, *add_head = NULL; -	struct list_head tmp_add_list, tmp_del_list; +	struct hlist_head tmp_add_list, tmp_del_list; +	struct i40e_mac_filter *f, *add_head = NULL;  	struct i40e_hw *hw = &vsi->back->hw; +	unsigned int failed_filters = 0; +	unsigned int vlan_filters = 0;  	bool promisc_changed = false;  	char vsi_name[16] = "PF";  	int filter_list_len = 0; -	u32 changed_flags = 0;  	i40e_status aq_ret = 0; -	int retval = 0; +	u32 changed_flags = 0; +	struct hlist_node *h;  	struct i40e_pf *pf;  	int num_add = 0;  	int num_del = 0; -	int aq_err = 0; +	int retval = 0;  	u16 cmd_flags;  	int list_size; -	int fcnt; +	int bkt;  	/* empty array typed pointers, kcalloc later */  	struct i40e_aqc_add_macvlan_element_data *add_list; @@ -1856,8 +2046,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)  		vsi->current_netdev_flags = vsi->netdev->flags;  	} -	INIT_LIST_HEAD(&tmp_add_list); -	INIT_LIST_HEAD(&tmp_del_list); +	INIT_HLIST_HEAD(&tmp_add_list); +	INIT_HLIST_HEAD(&tmp_del_list);  	if (vsi->type == I40E_VSI_SRIOV)  		snprintf(vsi_name, sizeof(vsi_name) - 1, "VF %d", vsi->vf_id); @@ -1867,43 +2057,64 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)  	if (vsi->flags & I40E_VSI_FLAG_FILTER_CHANGED) {  		vsi->flags &= ~I40E_VSI_FLAG_FILTER_CHANGED; -		spin_lock_bh(&vsi->mac_filter_list_lock); +		spin_lock_bh(&vsi->mac_filter_hash_lock);  		/* Create a list of filters to delete. */ -		list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { +		hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {  			if (f->state == I40E_FILTER_REMOVE) { -				WARN_ON(f->counter != 0);  				/* Move the element into temporary del_list */ -				list_move_tail(&f->list, &tmp_del_list); -				vsi->active_filters--; +				hash_del(&f->hlist); +				hlist_add_head(&f->hlist, &tmp_del_list); + +				/* Avoid counting removed filters */ +				continue;  			}  			if (f->state == I40E_FILTER_NEW) { -				WARN_ON(f->counter == 0); -				/* Move the element into temporary add_list */ -				list_move_tail(&f->list, &tmp_add_list); +				hash_del(&f->hlist); +				hlist_add_head(&f->hlist, &tmp_add_list);  			} + +			/* Count the number of active (current and new) VLAN +			 * filters we have now. Does not count filters which +			 * are marked for deletion. +			 */ +			if (f->vlan > 0) +				vlan_filters++;  		} -		spin_unlock_bh(&vsi->mac_filter_list_lock); + +		retval = i40e_correct_mac_vlan_filters(vsi, +						       &tmp_add_list, +						       &tmp_del_list, +						       vlan_filters); +		if (retval) +			goto err_no_memory_locked; + +		spin_unlock_bh(&vsi->mac_filter_hash_lock);  	}  	/* Now process 'del_list' outside the lock */ -	if (!list_empty(&tmp_del_list)) { +	if (!hlist_empty(&tmp_del_list)) {  		filter_list_len = hw->aq.asq_buf_size /  			    sizeof(struct i40e_aqc_remove_macvlan_element_data);  		list_size = filter_list_len *  			    sizeof(struct i40e_aqc_remove_macvlan_element_data);  		del_list = kzalloc(list_size, GFP_ATOMIC); -		if (!del_list) { -			/* Undo VSI's MAC filter entry element updates */ -			spin_lock_bh(&vsi->mac_filter_list_lock); -			i40e_undo_del_filter_entries(vsi, &tmp_del_list); -			spin_unlock_bh(&vsi->mac_filter_list_lock); -			retval = -ENOMEM; -			goto out; -		} +		if (!del_list) +			goto err_no_memory; -		list_for_each_entry_safe(f, ftmp, &tmp_del_list, list) { +		hlist_for_each_entry_safe(f, h, &tmp_del_list, hlist) {  			cmd_flags = 0; +			/* handle broadcast filters by updating the broadcast +			 * promiscuous flag instead of deleting a MAC filter. +			 */ +			if (is_broadcast_ether_addr(f->macaddr)) { +				i40e_aqc_broadcast_filter(vsi, vsi_name, f); + +				hlist_del(&f->hlist); +				kfree(f); +				continue; +			} +  			/* add to delete list */  			ether_addr_copy(del_list[num_del].mac_addr, f->macaddr);  			if (f->vlan == I40E_VLAN_ANY) { @@ -1920,73 +2131,57 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)  			/* flush a full buffer */  			if (num_del == filter_list_len) { -				aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, -								del_list, -								num_del, NULL); -				aq_err = hw->aq.asq_last_status; -				num_del = 0; +				i40e_aqc_del_filters(vsi, vsi_name, del_list, +						     num_del, &retval);  				memset(del_list, 0, list_size); - -				/* Explicitly ignore and do not report when -				 * firmware returns ENOENT. -				 */ -				if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) { -					retval = -EIO; -					dev_info(&pf->pdev->dev, -						 "ignoring delete macvlan error on %s, err %s, aq_err %s\n", -						 vsi_name, -						 i40e_stat_str(hw, aq_ret), -						 i40e_aq_str(hw, aq_err)); -				} +				num_del = 0;  			}  			/* Release memory for MAC filter entries which were  			 * synced up with HW.  			 */ -			list_del(&f->list); +			hlist_del(&f->hlist);  			kfree(f);  		}  		if (num_del) { -			aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, del_list, -							num_del, NULL); -			aq_err = hw->aq.asq_last_status; -			num_del = 0; - -			/* Explicitly ignore and do not report when firmware -			 * returns ENOENT. -			 */ -			if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) { -				retval = -EIO; -				dev_info(&pf->pdev->dev, -					 "ignoring delete macvlan error on %s, err %s aq_err %s\n", -					 vsi_name, -					 i40e_stat_str(hw, aq_ret), -					 i40e_aq_str(hw, aq_err)); -			} +			i40e_aqc_del_filters(vsi, vsi_name, del_list, +					     num_del, &retval);  		}  		kfree(del_list);  		del_list = NULL;  	} -	if (!list_empty(&tmp_add_list)) { +	if (!hlist_empty(&tmp_add_list)) {  		/* Do all the adds now. */  		filter_list_len = hw->aq.asq_buf_size /  			       sizeof(struct i40e_aqc_add_macvlan_element_data);  		list_size = filter_list_len *  			       sizeof(struct i40e_aqc_add_macvlan_element_data);  		add_list = kzalloc(list_size, GFP_ATOMIC); -		if (!add_list) { -			retval = -ENOMEM; -			goto out; -		} +		if (!add_list) +			goto err_no_memory; +  		num_add = 0; -		list_for_each_entry(f, &tmp_add_list, list) { +		hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {  			if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC,  				     &vsi->state)) {  				f->state = I40E_FILTER_FAILED;  				continue;  			} + +			/* handle broadcast filters by updating the broadcast +			 * promiscuous flag instead of adding a MAC filter. +			 */ +			if (is_broadcast_ether_addr(f->macaddr)) { +				u64 key = i40e_addr_to_hkey(f->macaddr); +				i40e_aqc_broadcast_filter(vsi, vsi_name, f); + +				hlist_del(&f->hlist); +				hash_add(vsi->mac_filter_hash, &f->hlist, key); +				continue; +			} +  			/* add to add array */  			if (num_add == 0)  				add_head = f; @@ -2000,88 +2195,70 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)  					cpu_to_le16((u16)(f->vlan));  			}  			add_list[num_add].queue_number = 0; +			/* set invalid match method for later detection */ +			add_list[num_add].match_method = I40E_AQC_MM_ERR_NO_RES;  			cmd_flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;  			add_list[num_add].flags = cpu_to_le16(cmd_flags);  			num_add++;  			/* flush a full buffer */  			if (num_add == filter_list_len) { -				aq_ret = i40e_aq_add_macvlan(hw, vsi->seid, -							     add_list, num_add, -							     NULL); -				aq_err = hw->aq.asq_last_status; -				fcnt = i40e_update_filter_state(num_add, -								add_list, -								add_head, -								aq_ret); -				vsi->active_filters += fcnt; - -				if (fcnt != num_add) { -					promisc_changed = true; -					set_bit(__I40E_FILTER_OVERFLOW_PROMISC, -						&vsi->state); -					vsi->promisc_threshold = -						(vsi->active_filters * 3) / 4; -					dev_warn(&pf->pdev->dev, -						 "Error %s adding RX filters on %s, promiscuous mode forced on\n", -						 i40e_aq_str(hw, aq_err), -						 vsi_name); -				} +				i40e_aqc_add_filters(vsi, vsi_name, add_list, +						     add_head, num_add, +						     &promisc_changed);  				memset(add_list, 0, list_size);  				num_add = 0;  			}  		}  		if (num_add) { -			aq_ret = i40e_aq_add_macvlan(hw, vsi->seid, -						     add_list, num_add, NULL); -			aq_err = hw->aq.asq_last_status; -			fcnt = i40e_update_filter_state(num_add, add_list, -							add_head, aq_ret); -			vsi->active_filters += fcnt; -			if (fcnt != num_add) { -				promisc_changed = true; -				set_bit(__I40E_FILTER_OVERFLOW_PROMISC, -					&vsi->state); -				vsi->promisc_threshold = -						(vsi->active_filters * 3) / 4; -				dev_warn(&pf->pdev->dev, -					 "Error %s adding RX filters on %s, promiscuous mode forced on\n", -					 i40e_aq_str(hw, aq_err), vsi_name); -			} +			i40e_aqc_add_filters(vsi, vsi_name, add_list, add_head, +					     num_add, &promisc_changed);  		}  		/* Now move all of the filters from the temp add list back to  		 * the VSI's list.  		 */ -		spin_lock_bh(&vsi->mac_filter_list_lock); -		list_for_each_entry_safe(f, ftmp, &tmp_add_list, list) { -			list_move_tail(&f->list, &vsi->mac_filter_list); +		spin_lock_bh(&vsi->mac_filter_hash_lock); +		hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) { +			u64 key = i40e_addr_to_hkey(f->macaddr); + +			hlist_del(&f->hlist); +			hash_add(vsi->mac_filter_hash, &f->hlist, key);  		} -		spin_unlock_bh(&vsi->mac_filter_list_lock); +		spin_unlock_bh(&vsi->mac_filter_hash_lock);  		kfree(add_list);  		add_list = NULL;  	} -	/* Check to see if we can drop out of overflow promiscuous mode. */ +	/* Determine the number of active and failed filters. */ +	spin_lock_bh(&vsi->mac_filter_hash_lock); +	vsi->active_filters = 0; +	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) { +		if (f->state == I40E_FILTER_ACTIVE) +			vsi->active_filters++; +		else if (f->state == I40E_FILTER_FAILED) +			failed_filters++; +	} +	spin_unlock_bh(&vsi->mac_filter_hash_lock); + +	/* If promiscuous mode has changed, we need to calculate a new +	 * threshold for when we are safe to exit +	 */ +	if (promisc_changed) +		vsi->promisc_threshold = (vsi->active_filters * 3) / 4; + +	/* Check if we are able to exit overflow promiscuous mode. We can +	 * safely exit if we didn't just enter, we no longer have any failed +	 * filters, and we have reduced filters below the threshold value. +	 */  	if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) && +	    !promisc_changed && !failed_filters &&  	    (vsi->active_filters < vsi->promisc_threshold)) { -		int failed_count = 0; -		/* See if we have any failed filters. We can't drop out of -		 * promiscuous until these have all been deleted. -		 */ -		spin_lock_bh(&vsi->mac_filter_list_lock); -		list_for_each_entry(f, &vsi->mac_filter_list, list) { -			if (f->state == I40E_FILTER_FAILED) -				failed_count++; -		} -		spin_unlock_bh(&vsi->mac_filter_list_lock); -		if (!failed_count) { -			dev_info(&pf->pdev->dev, -				 "filter logjam cleared on %s, leaving overflow promiscuous mode\n", -				 vsi_name); -			clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state); -			promisc_changed = true; -			vsi->promisc_threshold = 0; -		} +		dev_info(&pf->pdev->dev, +			 "filter logjam cleared on %s, leaving overflow promiscuous mode\n", +			 vsi_name); +		clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state); +		promisc_changed = true; +		vsi->promisc_threshold = 0;  	}  	/* if the VF is not trusted do not do promisc */ @@ -2201,6 +2378,18 @@ out:  	clear_bit(__I40E_CONFIG_BUSY, &vsi->state);  	return retval; + +err_no_memory: +	/* Restore elements on the temporary add and delete lists */ +	spin_lock_bh(&vsi->mac_filter_hash_lock); +err_no_memory_locked: +	i40e_undo_filter_entries(vsi, &tmp_del_list); +	i40e_undo_filter_entries(vsi, &tmp_add_list); +	spin_unlock_bh(&vsi->mac_filter_hash_lock); + +	vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; +	clear_bit(__I40E_CONFIG_BUSY, &vsi->state); +	return -ENOMEM;  }  /** @@ -2239,13 +2428,8 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)  static int i40e_change_mtu(struct net_device *netdev, int new_mtu)  {  	struct i40e_netdev_priv *np = netdev_priv(netdev); -	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;  	struct i40e_vsi *vsi = np->vsi; -	/* MTU < 68 is an error and causes problems on some kernels */ -	if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER)) -		return -EINVAL; -  	netdev_info(netdev, "changing MTU from %d to %d\n",  		    netdev->mtu, new_mtu);  	netdev->mtu = new_mtu; @@ -2354,88 +2538,54 @@ static void i40e_vlan_rx_register(struct net_device *netdev, u32 features)  }  /** - * i40e_vsi_add_vlan - Add vsi membership for given vlan + * i40e_add_vlan_all_mac - Add a MAC/VLAN filter for each existing MAC address   * @vsi: the vsi being configured   * @vid: vlan id to be added (0 = untagged only , -1 = any) + * + * This is a helper function for adding a new MAC/VLAN filter with the + * specified VLAN for each existing MAC address already in the hash table. + * This function does *not* perform any accounting to update filters based on + * VLAN mode. + * + * NOTE: this function expects to be called while under the + * mac_filter_hash_lock   **/ -int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) +int i40e_add_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)  { -	struct i40e_mac_filter *f, *ftmp, *add_f; -	bool is_netdev, is_vf; - -	is_vf = (vsi->type == I40E_VSI_SRIOV); -	is_netdev = !!(vsi->netdev); - -	/* Locked once because all functions invoked below iterates list*/ -	spin_lock_bh(&vsi->mac_filter_list_lock); - -	if (is_netdev) { -		add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, vid, -					is_vf, is_netdev); -		if (!add_f) { -			dev_info(&vsi->back->pdev->dev, -				 "Could not add vlan filter %d for %pM\n", -				 vid, vsi->netdev->dev_addr); -			spin_unlock_bh(&vsi->mac_filter_list_lock); -			return -ENOMEM; -		} -	} +	struct i40e_mac_filter *f, *add_f; +	struct hlist_node *h; +	int bkt; -	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { -		add_f = i40e_add_filter(vsi, f->macaddr, vid, is_vf, is_netdev); +	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { +		if (f->state == I40E_FILTER_REMOVE) +			continue; +		add_f = i40e_add_filter(vsi, f->macaddr, vid);  		if (!add_f) {  			dev_info(&vsi->back->pdev->dev,  				 "Could not add vlan filter %d for %pM\n",  				 vid, f->macaddr); -			spin_unlock_bh(&vsi->mac_filter_list_lock);  			return -ENOMEM;  		}  	} -	/* Now if we add a vlan tag, make sure to check if it is the first -	 * tag (i.e. a "tag" -1 does exist) and if so replace the -1 "tag" -	 * with 0, so we now accept untagged and specified tagged traffic -	 * (and not all tags along with untagged) -	 */ -	if (vid > 0) { -		if (is_netdev && i40e_find_filter(vsi, vsi->netdev->dev_addr, -						  I40E_VLAN_ANY, -						  is_vf, is_netdev)) { -			i40e_del_filter(vsi, vsi->netdev->dev_addr, -					I40E_VLAN_ANY, is_vf, is_netdev); -			add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, 0, -						is_vf, is_netdev); -			if (!add_f) { -				dev_info(&vsi->back->pdev->dev, -					 "Could not add filter 0 for %pM\n", -					 vsi->netdev->dev_addr); -				spin_unlock_bh(&vsi->mac_filter_list_lock); -				return -ENOMEM; -			} -		} -	} +	return 0; +} -	/* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */ -	if (vid > 0 && !vsi->info.pvid) { -		list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { -			if (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY, -					      is_vf, is_netdev)) -				continue; -			i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY, -					is_vf, is_netdev); -			add_f = i40e_add_filter(vsi, f->macaddr, -						0, is_vf, is_netdev); -			if (!add_f) { -				dev_info(&vsi->back->pdev->dev, -					 "Could not add filter 0 for %pM\n", -					f->macaddr); -				spin_unlock_bh(&vsi->mac_filter_list_lock); -				return -ENOMEM; -			} -		} -	} +/** + * i40e_vsi_add_vlan - Add VSI membership for given VLAN + * @vsi: the VSI being configured + * @vid: VLAN id to be added (0 = untagged only , -1 = any) + **/ +int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) +{ +	int err; -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	/* Locked once because all functions invoked below iterates list*/ +	spin_lock_bh(&vsi->mac_filter_hash_lock); +	err = i40e_add_vlan_all_mac(vsi, vid); +	spin_unlock_bh(&vsi->mac_filter_hash_lock); +	if (err) +		return err;  	/* schedule our worker thread which will take care of  	 * applying the new filter changes @@ -2445,82 +2595,45 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)  }  /** - * i40e_vsi_kill_vlan - Remove vsi membership for given vlan + * i40e_rm_vlan_all_mac - Remove MAC/VLAN pair for all MAC with the given VLAN   * @vsi: the vsi being configured   * @vid: vlan id to be removed (0 = untagged only , -1 = any)   * - * Return: 0 on success or negative otherwise - **/ -int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) + * This function should be used to remove all VLAN filters which match the + * given VID. It does not schedule the service event and does not take the + * mac_filter_hash_lock so it may be combined with other operations under + * a single invocation of the mac_filter_hash_lock. + * + * NOTE: this function expects to be called while under the + * mac_filter_hash_lock + */ +void i40e_rm_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)  { -	struct net_device *netdev = vsi->netdev; -	struct i40e_mac_filter *f, *ftmp, *add_f; -	bool is_vf, is_netdev; -	int filter_count = 0; - -	is_vf = (vsi->type == I40E_VSI_SRIOV); -	is_netdev = !!(netdev); - -	/* Locked once because all functions invoked below iterates list */ -	spin_lock_bh(&vsi->mac_filter_list_lock); - -	if (is_netdev) -		i40e_del_filter(vsi, netdev->dev_addr, vid, is_vf, is_netdev); - -	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) -		i40e_del_filter(vsi, f->macaddr, vid, is_vf, is_netdev); - -	/* go through all the filters for this VSI and if there is only -	 * vid == 0 it means there are no other filters, so vid 0 must -	 * be replaced with -1. This signifies that we should from now -	 * on accept any traffic (with any tag present, or untagged) -	 */ -	list_for_each_entry(f, &vsi->mac_filter_list, list) { -		if (is_netdev) { -			if (f->vlan && -			    ether_addr_equal(netdev->dev_addr, f->macaddr)) -				filter_count++; -		} - -		if (f->vlan) -			filter_count++; -	} - -	if (!filter_count && is_netdev) { -		i40e_del_filter(vsi, netdev->dev_addr, 0, is_vf, is_netdev); -		f = i40e_add_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, -				    is_vf, is_netdev); -		if (!f) { -			dev_info(&vsi->back->pdev->dev, -				 "Could not add filter %d for %pM\n", -				 I40E_VLAN_ANY, netdev->dev_addr); -			spin_unlock_bh(&vsi->mac_filter_list_lock); -			return -ENOMEM; -		} -	} +	struct i40e_mac_filter *f; +	struct hlist_node *h; +	int bkt; -	if (!filter_count) { -		list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { -			i40e_del_filter(vsi, f->macaddr, 0, is_vf, is_netdev); -			add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY, -						is_vf, is_netdev); -			if (!add_f) { -				dev_info(&vsi->back->pdev->dev, -					 "Could not add filter %d for %pM\n", -					 I40E_VLAN_ANY, f->macaddr); -				spin_unlock_bh(&vsi->mac_filter_list_lock); -				return -ENOMEM; -			} -		} +	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { +		if (f->vlan == vid) +			__i40e_del_filter(vsi, f);  	} +} -	spin_unlock_bh(&vsi->mac_filter_list_lock); +/** + * i40e_vsi_kill_vlan - Remove VSI membership for given VLAN + * @vsi: the VSI being configured + * @vid: VLAN id to be removed (0 = untagged only , -1 = any) + **/ +void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) +{ +	spin_lock_bh(&vsi->mac_filter_hash_lock); +	i40e_rm_vlan_all_mac(vsi, vid); +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	/* schedule our worker thread which will take care of  	 * applying the new filter changes  	 */  	i40e_service_event_schedule(vsi->back); -	return 0;  }  /** @@ -2542,7 +2655,7 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev,  	struct i40e_vsi *vsi = np->vsi;  	int ret = 0; -	if (vid > 4095) +	if (vid >= VLAN_N_VID)  		return -EINVAL;  	/* If the network stack called us with vid = 0 then @@ -2554,7 +2667,7 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev,  	if (vid)  		ret = i40e_vsi_add_vlan(vsi, vid); -	if (!ret && (vid < VLAN_N_VID)) +	if (!ret)  		set_bit(vid, vsi->active_vlans);  	return ret; @@ -3322,6 +3435,33 @@ static irqreturn_t i40e_msix_clean_rings(int irq, void *data)  }  /** + * i40e_irq_affinity_notify - Callback for affinity changes + * @notify: context as to what irq was changed + * @mask: the new affinity mask + * + * This is a callback function used by the irq_set_affinity_notifier function + * so that we may register to receive changes to the irq affinity masks. + **/ +static void i40e_irq_affinity_notify(struct irq_affinity_notify *notify, +				     const cpumask_t *mask) +{ +	struct i40e_q_vector *q_vector = +		container_of(notify, struct i40e_q_vector, affinity_notify); + +	q_vector->affinity_mask = *mask; +} + +/** + * i40e_irq_affinity_release - Callback for affinity notifier release + * @ref: internal core kernel usage + * + * This is a callback function used by the irq_set_affinity_notifier function + * to inform the current notification subscriber that they will no longer + * receive notifications. + **/ +static void i40e_irq_affinity_release(struct kref *ref) {} + +/**   * i40e_vsi_request_irq_msix - Initialize MSI-X interrupts   * @vsi: the VSI being configured   * @basename: name for the vector @@ -3336,10 +3476,13 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)  	int rx_int_idx = 0;  	int tx_int_idx = 0;  	int vector, err; +	int irq_num;  	for (vector = 0; vector < q_vectors; vector++) {  		struct i40e_q_vector *q_vector = vsi->q_vectors[vector]; +		irq_num = pf->msix_entries[base + vector].vector; +  		if (q_vector->tx.ring && q_vector->rx.ring) {  			snprintf(q_vector->name, sizeof(q_vector->name) - 1,  				 "%s-%s-%d", basename, "TxRx", rx_int_idx++); @@ -3354,7 +3497,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)  			/* skip this unused q_vector */  			continue;  		} -		err = request_irq(pf->msix_entries[base + vector].vector, +		err = request_irq(irq_num,  				  vsi->irq_handler,  				  0,  				  q_vector->name, @@ -3364,9 +3507,13 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)  				 "MSIX request_irq failed, error: %d\n", err);  			goto free_queue_irqs;  		} + +		/* register for affinity change notifications */ +		q_vector->affinity_notify.notify = i40e_irq_affinity_notify; +		q_vector->affinity_notify.release = i40e_irq_affinity_release; +		irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);  		/* assign the mask for this irq */ -		irq_set_affinity_hint(pf->msix_entries[base + vector].vector, -				      &q_vector->affinity_mask); +		irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);  	}  	vsi->irqs_ready = true; @@ -3375,10 +3522,10 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)  free_queue_irqs:  	while (vector) {  		vector--; -		irq_set_affinity_hint(pf->msix_entries[base + vector].vector, -				      NULL); -		free_irq(pf->msix_entries[base + vector].vector, -			 &(vsi->q_vectors[vector])); +		irq_num = pf->msix_entries[base + vector].vector; +		irq_set_affinity_notifier(irq_num, NULL); +		irq_set_affinity_hint(irq_num, NULL); +		free_irq(irq_num, &vsi->q_vectors[vector]);  	}  	return err;  } @@ -3480,7 +3627,7 @@ static irqreturn_t i40e_intr(int irq, void *data)  	    (ena_mask & I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK)) {  		ena_mask &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK;  		icr0 &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK; -		dev_info(&pf->pdev->dev, "cleared PE_CRITERR\n"); +		dev_dbg(&pf->pdev->dev, "cleared PE_CRITERR\n");  	}  	/* only q0 is used in MSI/Legacy mode, and none are used in MSIX */ @@ -3973,30 +4120,36 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)  }  /** - * i40e_vsi_control_rings - Start or stop a VSI's rings + * i40e_vsi_start_rings - Start a VSI's rings   * @vsi: the VSI being configured - * @enable: start or stop the rings   **/ -int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool request) +int i40e_vsi_start_rings(struct i40e_vsi *vsi)  {  	int ret = 0;  	/* do rx first for enable and last for disable */ -	if (request) { -		ret = i40e_vsi_control_rx(vsi, request); -		if (ret) -			return ret; -		ret = i40e_vsi_control_tx(vsi, request); -	} else { -		/* Ignore return value, we need to shutdown whatever we can */ -		i40e_vsi_control_tx(vsi, request); -		i40e_vsi_control_rx(vsi, request); -	} +	ret = i40e_vsi_control_rx(vsi, true); +	if (ret) +		return ret; +	ret = i40e_vsi_control_tx(vsi, true);  	return ret;  }  /** + * i40e_vsi_stop_rings - Stop a VSI's rings + * @vsi: the VSI being configured + **/ +void i40e_vsi_stop_rings(struct i40e_vsi *vsi) +{ +	/* do rx first for enable and last for disable +	 * Ignore return value, we need to shutdown whatever we can +	 */ +	i40e_vsi_control_tx(vsi, false); +	i40e_vsi_control_rx(vsi, false); +} + +/**   * i40e_vsi_free_irq - Free the irq association with the OS   * @vsi: the VSI being configured   **/ @@ -4017,19 +4170,23 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi)  		vsi->irqs_ready = false;  		for (i = 0; i < vsi->num_q_vectors; i++) { -			u16 vector = i + base; +			int irq_num; +			u16 vector; + +			vector = i + base; +			irq_num = pf->msix_entries[vector].vector;  			/* free only the irqs that were actually requested */  			if (!vsi->q_vectors[i] ||  			    !vsi->q_vectors[i]->num_ringpairs)  				continue; +			/* clear the affinity notifier in the IRQ descriptor */ +			irq_set_affinity_notifier(irq_num, NULL);  			/* clear the affinity_mask in the IRQ descriptor */ -			irq_set_affinity_hint(pf->msix_entries[vector].vector, -					      NULL); -			synchronize_irq(pf->msix_entries[vector].vector); -			free_irq(pf->msix_entries[vector].vector, -				 vsi->q_vectors[i]); +			irq_set_affinity_hint(irq_num, NULL); +			synchronize_irq(irq_num); +			free_irq(irq_num, vsi->q_vectors[i]);  			/* Tear down the interrupt queue link list  			 * @@ -5116,12 +5273,16 @@ out:   */  void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)  { +	enum i40e_aq_link_speed new_speed;  	char *speed = "Unknown";  	char *fc = "Unknown"; -	if (vsi->current_isup == isup) +	new_speed = vsi->back->hw.phy.link_info.link_speed; + +	if ((vsi->current_isup == isup) && (vsi->current_speed == new_speed))  		return;  	vsi->current_isup = isup; +	vsi->current_speed = new_speed;  	if (!isup) {  		netdev_info(vsi->netdev, "NIC Link is Down\n");  		return; @@ -5143,6 +5304,9 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)  	case I40E_LINK_SPEED_20GB:  		speed = "20 G";  		break; +	case I40E_LINK_SPEED_25GB: +		speed = "25 G"; +		break;  	case I40E_LINK_SPEED_10GB:  		speed = "10 G";  		break; @@ -5190,7 +5354,7 @@ static int i40e_up_complete(struct i40e_vsi *vsi)  		i40e_configure_msi_and_legacy(vsi);  	/* start rings */ -	err = i40e_vsi_control_rings(vsi, true); +	err = i40e_vsi_start_rings(vsi);  	if (err)  		return err; @@ -5287,7 +5451,7 @@ void i40e_down(struct i40e_vsi *vsi)  		netif_tx_disable(vsi->netdev);  	}  	i40e_vsi_disable_irq(vsi); -	i40e_vsi_control_rings(vsi, false); +	i40e_vsi_stop_rings(vsi);  	i40e_napi_disable_all(vsi);  	for (i = 0; i < vsi->num_queue_pairs; i++) { @@ -5833,19 +5997,6 @@ static void i40e_handle_lan_overflow_event(struct i40e_pf *pf,  }  /** - * i40e_service_event_complete - Finish up the service event - * @pf: board private structure - **/ -static void i40e_service_event_complete(struct i40e_pf *pf) -{ -	WARN_ON(!test_bit(__I40E_SERVICE_SCHED, &pf->state)); - -	/* flush memory to make sure state is correct before next watchog */ -	smp_mb__before_atomic(); -	clear_bit(__I40E_SERVICE_SCHED, &pf->state); -} - -/**   * i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters   * @pf: board private structure   **/ @@ -6670,7 +6821,6 @@ static int i40e_vsi_clear(struct i40e_vsi *vsi);  static void i40e_fdir_sb_setup(struct i40e_pf *pf)  {  	struct i40e_vsi *vsi; -	int i;  	/* quick workaround for an NVM issue that leaves a critical register  	 * uninitialized @@ -6681,6 +6831,7 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf)  			0xeacb7d61, 0xaa4f05b6, 0x9c5c89ed, 0xfc425ddb,  			0xa4654832, 0xfc7461d4, 0x8f827619, 0xf5c63c21,  			0x95b3a76d}; +		int i;  		for (i = 0; i <= I40E_GLQF_HKEY_MAX_INDEX; i++)  			wr32(&pf->hw, I40E_GLQF_HKEY(i), hkey[i]); @@ -6690,13 +6841,7 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf)  		return;  	/* find existing VSI and see if it needs configuring */ -	vsi = NULL; -	for (i = 0; i < pf->num_alloc_vsi; i++) { -		if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { -			vsi = pf->vsi[i]; -			break; -		} -	} +	vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR);  	/* create a new VSI if none exists */  	if (!vsi) { @@ -6718,15 +6863,12 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf)   **/  static void i40e_fdir_teardown(struct i40e_pf *pf)  { -	int i; +	struct i40e_vsi *vsi;  	i40e_fdir_filter_exit(pf); -	for (i = 0; i < pf->num_alloc_vsi; i++) { -		if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { -			i40e_vsi_release(pf->vsi[i]); -			break; -		} -	} +	vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR); +	if (vsi) +		i40e_vsi_release(vsi);  }  /** @@ -7163,10 +7305,12 @@ static void i40e_service_task(struct work_struct *work)  	/* don't bother with service tasks if a reset is in progress */  	if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) { -		i40e_service_event_complete(pf);  		return;  	} +	if (test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state)) +		return; +  	i40e_detect_recover_hung(pf);  	i40e_sync_filters_subtask(pf);  	i40e_reset_subtask(pf); @@ -7179,7 +7323,9 @@ static void i40e_service_task(struct work_struct *work)  	i40e_sync_udp_filters_subtask(pf);  	i40e_clean_adminq_subtask(pf); -	i40e_service_event_complete(pf); +	/* flush memory to make sure state is correct before next watchdog */ +	smp_mb__before_atomic(); +	clear_bit(__I40E_SERVICE_SCHED, &pf->state);  	/* If the tasks have taken longer than one timer cycle or there  	 * is more work to be done, reschedule the service task now @@ -7354,7 +7500,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)  				pf->rss_table_size : 64;  	vsi->netdev_registered = false;  	vsi->work_limit = I40E_DEFAULT_IRQ_WORK; -	INIT_LIST_HEAD(&vsi->mac_filter_list); +	hash_init(vsi->mac_filter_hash);  	vsi->irqs_ready = false;  	ret = i40e_set_num_rings_in_vsi(vsi); @@ -7369,7 +7515,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)  	i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings);  	/* Initialize VSI lock */ -	spin_lock_init(&vsi->mac_filter_list_lock); +	spin_lock_init(&vsi->mac_filter_hash_lock);  	pf->vsi[vsi_idx] = vsi;  	ret = vsi_idx;  	goto unlock_pf; @@ -8345,8 +8491,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)  		i40e_pf_config_rss(pf);  	} -	dev_info(&pf->pdev->dev, "RSS count/HW max RSS count:  %d/%d\n", -		 pf->alloc_rss_size, pf->rss_size_max); +	dev_info(&pf->pdev->dev, "User requested queue count/HW max RSS count:  %d/%d\n", +		 vsi->req_queue_pairs, pf->rss_size_max);  	return pf->alloc_rss_size;  } @@ -8489,15 +8635,6 @@ static int i40e_sw_init(struct i40e_pf *pf)  	int err = 0;  	int size; -	pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE, -				(NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)); -	if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) { -		if (I40E_DEBUG_USER & debug) -			pf->hw.debug_mask = debug; -		pf->msg_enable = netif_msg_init((debug & ~I40E_DEBUG_USER), -						I40E_DEFAULT_MSG_ENABLE); -	} -  	/* Set default capability flags */  	pf->flags = I40E_FLAG_RX_CSUM_ENABLED |  		    I40E_FLAG_MSI_ENABLED     | @@ -8605,7 +8742,8 @@ static int i40e_sw_init(struct i40e_pf *pf)  			     I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE |  			     I40E_FLAG_NO_PCI_LINK_CHECK |  			     I40E_FLAG_USE_SET_LLDP_MIB | -			     I40E_FLAG_GENEVE_OFFLOAD_CAPABLE; +			     I40E_FLAG_GENEVE_OFFLOAD_CAPABLE | +			     I40E_FLAG_PTP_L4_CAPABLE;  	} else if ((pf->hw.aq.api_maj_ver > 1) ||  		   ((pf->hw.aq.api_maj_ver == 1) &&  		    (pf->hw.aq.api_min_ver > 4))) { @@ -9037,10 +9175,6 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,  				       0, 0, nlflags, filter_mask, NULL);  } -/* Hardware supports L4 tunnel length of 128B (=2^7) which includes - * inner mac plus all inner ethertypes. - */ -#define I40E_MAX_TUNNEL_HDR_LEN 128  /**   * i40e_features_check - Validate encapsulated packet conforms to limits   * @skb: skb buff @@ -9051,12 +9185,52 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,  					     struct net_device *dev,  					     netdev_features_t features)  { -	if (skb->encapsulation && -	    ((skb_inner_network_header(skb) - skb_transport_header(skb)) > -	     I40E_MAX_TUNNEL_HDR_LEN)) -		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); +	size_t len; + +	/* No point in doing any of this if neither checksum nor GSO are +	 * being requested for this frame.  We can rule out both by just +	 * checking for CHECKSUM_PARTIAL +	 */ +	if (skb->ip_summed != CHECKSUM_PARTIAL) +		return features; + +	/* We cannot support GSO if the MSS is going to be less than +	 * 64 bytes.  If it is then we need to drop support for GSO. +	 */ +	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64)) +		features &= ~NETIF_F_GSO_MASK; + +	/* MACLEN can support at most 63 words */ +	len = skb_network_header(skb) - skb->data; +	if (len & ~(63 * 2)) +		goto out_err; + +	/* IPLEN and EIPLEN can support at most 127 dwords */ +	len = skb_transport_header(skb) - skb_network_header(skb); +	if (len & ~(127 * 4)) +		goto out_err; + +	if (skb->encapsulation) { +		/* L4TUNLEN can support 127 words */ +		len = skb_inner_network_header(skb) - skb_transport_header(skb); +		if (len & ~(127 * 2)) +			goto out_err; + +		/* IPLEN can support at most 127 dwords */ +		len = skb_inner_transport_header(skb) - +		      skb_inner_network_header(skb); +		if (len & ~(127 * 4)) +			goto out_err; +	} + +	/* No need to validate L4LEN as TCP is the only protocol with a +	 * a flexible value and we support all possible values supported +	 * by TCP, which is at most 15 dwords +	 */  	return features; +out_err: +	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);  }  static const struct net_device_ops i40e_netdev_ops = { @@ -9109,6 +9283,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)  	struct i40e_hw *hw = &pf->hw;  	struct i40e_netdev_priv *np;  	struct net_device *netdev; +	u8 broadcast[ETH_ALEN];  	u8 mac_addr[ETH_ALEN];  	int etherdev_size; @@ -9169,20 +9344,38 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)  		 * which must be replaced by a normal filter.  		 */  		i40e_rm_default_mac_filter(vsi, mac_addr); -		spin_lock_bh(&vsi->mac_filter_list_lock); -		i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, true); -		spin_unlock_bh(&vsi->mac_filter_list_lock); +		spin_lock_bh(&vsi->mac_filter_hash_lock); +		i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY); +		spin_unlock_bh(&vsi->mac_filter_hash_lock);  	} else {  		/* relate the VSI_VMDQ name to the VSI_MAIN name */  		snprintf(netdev->name, IFNAMSIZ, "%sv%%d",  			 pf->vsi[pf->lan_vsi]->netdev->name);  		random_ether_addr(mac_addr); -		spin_lock_bh(&vsi->mac_filter_list_lock); -		i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, false); -		spin_unlock_bh(&vsi->mac_filter_list_lock); +		spin_lock_bh(&vsi->mac_filter_hash_lock); +		i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY); +		spin_unlock_bh(&vsi->mac_filter_hash_lock);  	} +	/* Add the broadcast filter so that we initially will receive +	 * broadcast packets. Note that when a new VLAN is first added the +	 * driver will convert all filters marked I40E_VLAN_ANY into VLAN +	 * specific filters as part of transitioning into "vlan" operation. +	 * When more VLANs are added, the driver will copy each existing MAC +	 * filter and add it for the new VLAN. +	 * +	 * Broadcast filters are handled specially by +	 * i40e_sync_filters_subtask, as the driver must to set the broadcast +	 * promiscuous bit instead of adding this directly as a MAC/VLAN +	 * filter. The subtask will update the correct broadcast promiscuous +	 * bits as VLANs become active or inactive. +	 */ +	eth_broadcast_addr(broadcast); +	spin_lock_bh(&vsi->mac_filter_hash_lock); +	i40e_add_filter(vsi, broadcast, I40E_VLAN_ANY); +	spin_unlock_bh(&vsi->mac_filter_hash_lock); +  	ether_addr_copy(netdev->dev_addr, mac_addr);  	ether_addr_copy(netdev->perm_addr, mac_addr); @@ -9198,6 +9391,11 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)  	i40e_fcoe_config_netdev(netdev, vsi);  #endif +	/* MTU range: 68 - 9706 */ +	netdev->min_mtu = ETH_MIN_MTU; +	netdev->max_mtu = I40E_MAX_RXBUFFER - +			  (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); +  	return 0;  } @@ -9260,11 +9458,12 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi)  static int i40e_add_vsi(struct i40e_vsi *vsi)  {  	int ret = -ENODEV; -	i40e_status aq_ret = 0;  	struct i40e_pf *pf = vsi->back;  	struct i40e_hw *hw = &pf->hw;  	struct i40e_vsi_context ctxt; -	struct i40e_mac_filter *f, *ftmp; +	struct i40e_mac_filter *f; +	struct hlist_node *h; +	int bkt;  	u8 enabled_tc = 0x1; /* TC0 enabled */  	int f_count = 0; @@ -9448,28 +9647,16 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)  		vsi->seid = ctxt.seid;  		vsi->id = ctxt.vsi_number;  	} -	/* Except FDIR VSI, for all othet VSI set the broadcast filter */ -	if (vsi->type != I40E_VSI_FDIR) { -		aq_ret = i40e_aq_set_vsi_broadcast(hw, vsi->seid, true, NULL); -		if (aq_ret) { -			ret = i40e_aq_rc_to_posix(aq_ret, -						  hw->aq.asq_last_status); -			dev_info(&pf->pdev->dev, -				 "set brdcast promisc failed, err %s, aq_err %s\n", -				 i40e_stat_str(hw, aq_ret), -				 i40e_aq_str(hw, hw->aq.asq_last_status)); -		} -	}  	vsi->active_filters = 0;  	clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state); -	spin_lock_bh(&vsi->mac_filter_list_lock); +	spin_lock_bh(&vsi->mac_filter_hash_lock);  	/* If macvlan filters already exist, force them to get loaded */ -	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { +	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {  		f->state = I40E_FILTER_NEW;  		f_count++;  	} -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	if (f_count) {  		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; @@ -9499,11 +9686,12 @@ err:   **/  int i40e_vsi_release(struct i40e_vsi *vsi)  { -	struct i40e_mac_filter *f, *ftmp; +	struct i40e_mac_filter *f; +	struct hlist_node *h;  	struct i40e_veb *veb = NULL;  	struct i40e_pf *pf;  	u16 uplink_seid; -	int i, n; +	int i, n, bkt;  	pf = vsi->back; @@ -9533,11 +9721,19 @@ int i40e_vsi_release(struct i40e_vsi *vsi)  		i40e_vsi_disable_irq(vsi);  	} -	spin_lock_bh(&vsi->mac_filter_list_lock); -	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) -		i40e_del_filter(vsi, f->macaddr, f->vlan, -				f->is_vf, f->is_netdev); -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	spin_lock_bh(&vsi->mac_filter_hash_lock); + +	/* clear the sync flag on all filters */ +	if (vsi->netdev) { +		__dev_uc_unsync(vsi->netdev, NULL); +		__dev_mc_unsync(vsi->netdev, NULL); +	} + +	/* make sure any remaining filters are marked for deletion */ +	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) +		__i40e_del_filter(vsi, f); + +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	i40e_sync_vsi_filters(vsi); @@ -10806,10 +11002,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	mutex_init(&hw->aq.asq_mutex);  	mutex_init(&hw->aq.arq_mutex); -	if (debug != -1) { -		pf->msg_enable = pf->hw.debug_mask; -		pf->msg_enable = debug; -	} +	pf->msg_enable = netif_msg_init(debug, +					NETIF_MSG_DRV | +					NETIF_MSG_PROBE | +					NETIF_MSG_LINK); +	if (debug < -1) +		pf->hw.debug_mask = debug;  	/* do a special CORER for clearing PXE mode once at init */  	if (hw->revision_id == 0 && @@ -10951,7 +11149,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	err = i40e_init_pf_dcb(pf);  	if (err) {  		dev_info(&pdev->dev, "DCB init failed %d, disabled\n", err); -		pf->flags &= ~(I40E_FLAG_DCB_CAPABLE & I40E_FLAG_DCB_ENABLED); +		pf->flags &= ~(I40E_FLAG_DCB_CAPABLE | I40E_FLAG_DCB_ENABLED);  		/* Continue without DCB enabled */  	}  #endif /* CONFIG_I40E_DCB */ @@ -11209,7 +11407,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  		dev_dbg(&pf->pdev->dev, "get supported phy types ret =  %s last_status =  %s\n",  			i40e_stat_str(&pf->hw, err),  			i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); -	pf->hw.phy.phy_types = le32_to_cpu(abilities.phy_type);  	/* Add a filter to drop all Flow control frames from any VSI from being  	 * transmitted. By doing so we stop a malicious VF from sending out @@ -11221,9 +11418,10 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  						       pf->main_vsi_seid);  	if ((pf->hw.device_id == I40E_DEV_ID_10G_BASE_T) || -	    (pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4)) -		pf->flags |= I40E_FLAG_HAVE_10GBASET_PHY; - +		(pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4)) +		pf->flags |= I40E_FLAG_PHY_CONTROLS_LEDS; +	if (pf->hw.device_id == I40E_DEV_ID_SFP_I_X722) +		pf->flags |= I40E_FLAG_HAVE_CRT_RETIMER;  	/* print a string summarizing features */  	i40e_print_features(pf); diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 954efe3118db..38ee18f11124 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -722,9 +722,20 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,  			*((u16 *)&bytes[2]) = hw->nvm_wait_opcode;  		} +		/* Clear error status on read */ +		if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) +			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; +  		return 0;  	} +	/* Clear status even it is not read and log */ +	if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) { +		i40e_debug(hw, I40E_DEBUG_NVM, +			   "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n"); +		hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; +	} +  	switch (hw->nvmupd_state) {  	case I40E_NVMUPD_STATE_INIT:  		status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno); @@ -1074,6 +1085,11 @@ void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode)  		}  		hw->nvm_wait_opcode = 0; +		if (hw->aq.arq_last_status) { +			hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR; +			return; +		} +  		switch (hw->nvmupd_state) {  		case I40E_NVMUPD_STATE_INIT_WAIT:  			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index 4660c5abc855..2551fc827444 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -144,6 +144,9 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,  							 u16 seid, bool enable,  							 u16 vid,  				struct i40e_asq_cmd_details *cmd_details); +i40e_status i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw, +				u16 seid, bool enable, u16 vid, +				struct i40e_asq_cmd_details *cmd_details);  i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,  				u16 seid, bool enable,  				struct i40e_asq_cmd_details *cmd_details); @@ -362,10 +365,18 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,  				u32 reg_addr, u32 reg_val,  				struct i40e_asq_cmd_details *cmd_details);  void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val); -i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, -				   u16 reg, u8 phy_addr, u16 *value); -i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, -				    u16 reg, u8 phy_addr, u16 value); +i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw, +					    u16 reg, u8 phy_addr, u16 *value); +i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw, +					     u16 reg, u8 phy_addr, u16 value); +i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw, +				u8 page, u16 reg, u8 phy_addr, u16 *value); +i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw, +				u8 page, u16 reg, u8 phy_addr, u16 value); +i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, u16 reg, +				   u8 phy_addr, u16 *value); +i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, u16 reg, +				    u8 phy_addr, u16 value);  u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);  i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,  				    u32 time, u32 interval); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index f1feceab758a..9e49ffafce28 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -159,16 +159,15 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)  {  	struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);  	struct timespec64 now, then; -	unsigned long flags;  	then = ns_to_timespec64(delta); -	spin_lock_irqsave(&pf->tmreg_lock, flags); +	mutex_lock(&pf->tmreg_lock);  	i40e_ptp_read(pf, &now);  	now = timespec64_add(now, then);  	i40e_ptp_write(pf, (const struct timespec64 *)&now); -	spin_unlock_irqrestore(&pf->tmreg_lock, flags); +	mutex_unlock(&pf->tmreg_lock);  	return 0;  } @@ -184,11 +183,10 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)  static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)  {  	struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps); -	unsigned long flags; -	spin_lock_irqsave(&pf->tmreg_lock, flags); +	mutex_lock(&pf->tmreg_lock);  	i40e_ptp_read(pf, ts); -	spin_unlock_irqrestore(&pf->tmreg_lock, flags); +	mutex_unlock(&pf->tmreg_lock);  	return 0;  } @@ -205,11 +203,10 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp,  			    const struct timespec64 *ts)  {  	struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps); -	unsigned long flags; -	spin_lock_irqsave(&pf->tmreg_lock, flags); +	mutex_lock(&pf->tmreg_lock);  	i40e_ptp_write(pf, ts); -	spin_unlock_irqrestore(&pf->tmreg_lock, flags); +	mutex_unlock(&pf->tmreg_lock);  	return 0;  } @@ -230,6 +227,47 @@ static int i40e_ptp_feature_enable(struct ptp_clock_info *ptp,  }  /** + * i40e_ptp_update_latch_events - Read I40E_PRTTSYN_STAT_1 and latch events + * @pf: the PF data structure + * + * This function reads I40E_PRTTSYN_STAT_1 and updates the corresponding timers + * for noticed latch events. This allows the driver to keep track of the first + * time a latch event was noticed which will be used to help clear out Rx + * timestamps for packets that got dropped or lost. + * + * This function will return the current value of I40E_PRTTSYN_STAT_1 and is + * expected to be called only while under the ptp_rx_lock. + **/ +static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf) +{ +	struct i40e_hw *hw = &pf->hw; +	u32 prttsyn_stat, new_latch_events; +	int  i; + +	prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1); +	new_latch_events = prttsyn_stat & ~pf->latch_event_flags; + +	/* Update the jiffies time for any newly latched timestamp. This +	 * ensures that we store the time that we first discovered a timestamp +	 * was latched by the hardware. The service task will later determine +	 * if we should free the latch and drop that timestamp should too much +	 * time pass. This flow ensures that we only update jiffies for new +	 * events latched since the last time we checked, and not all events +	 * currently latched, so that the service task accounting remains +	 * accurate. +	 */ +	for (i = 0; i < 4; i++) { +		if (new_latch_events & BIT(i)) +			pf->latch_events[i] = jiffies; +	} + +	/* Finally, we store the current status of the Rx timestamp latches */ +	pf->latch_event_flags = prttsyn_stat; + +	return prttsyn_stat; +} + +/**   * i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung   * @vsi: The VSI with the rings relevant to 1588   * @@ -242,10 +280,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)  {  	struct i40e_pf *pf = vsi->back;  	struct i40e_hw *hw = &pf->hw; -	struct i40e_ring *rx_ring; -	unsigned long rx_event; -	u32 prttsyn_stat; -	int n; +	int i;  	/* Since we cannot turn off the Rx timestamp logic if the device is  	 * configured for Tx timestamping, we check if Rx timestamping is @@ -255,42 +290,30 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)  	if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_rx)  		return; -	prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1); +	spin_lock_bh(&pf->ptp_rx_lock); -	/* Unless all four receive timestamp registers are latched, we are not -	 * concerned about a possible PTP Rx hang, so just update the timeout -	 * counter and exit. -	 */ -	if (!(prttsyn_stat & ((I40E_PRTTSYN_STAT_1_RXT0_MASK << -			       I40E_PRTTSYN_STAT_1_RXT0_SHIFT) | -			      (I40E_PRTTSYN_STAT_1_RXT1_MASK << -			       I40E_PRTTSYN_STAT_1_RXT1_SHIFT) | -			      (I40E_PRTTSYN_STAT_1_RXT2_MASK << -			       I40E_PRTTSYN_STAT_1_RXT2_SHIFT) | -			      (I40E_PRTTSYN_STAT_1_RXT3_MASK << -			       I40E_PRTTSYN_STAT_1_RXT3_SHIFT)))) { -		pf->last_rx_ptp_check = jiffies; -		return; -	} +	/* Update current latch times for Rx events */ +	i40e_ptp_get_rx_events(pf); -	/* Determine the most recent watchdog or rx_timestamp event. */ -	rx_event = pf->last_rx_ptp_check; -	for (n = 0; n < vsi->num_queue_pairs; n++) { -		rx_ring = vsi->rx_rings[n]; -		if (time_after(rx_ring->last_rx_timestamp, rx_event)) -			rx_event = rx_ring->last_rx_timestamp; +	/* Check all the currently latched Rx events and see whether they have +	 * been latched for over a second. It is assumed that any timestamp +	 * should have been cleared within this time, or else it was captured +	 * for a dropped frame that the driver never received. Thus, we will +	 * clear any timestamp that has been latched for over 1 second. +	 */ +	for (i = 0; i < 4; i++) { +		if ((pf->latch_event_flags & BIT(i)) && +		    time_is_before_jiffies(pf->latch_events[i] + HZ)) { +			rd32(hw, I40E_PRTTSYN_RXTIME_H(i)); +			pf->latch_event_flags &= ~BIT(i); +			pf->rx_hwtstamp_cleared++; +			dev_warn(&pf->pdev->dev, +				 "Clearing a missed Rx timestamp event for RXTIME[%d]\n", +				 i); +		}  	} -	/* Only need to read the high RXSTMP register to clear the lock */ -	if (time_is_before_jiffies(rx_event + 5 * HZ)) { -		rd32(hw, I40E_PRTTSYN_RXTIME_H(0)); -		rd32(hw, I40E_PRTTSYN_RXTIME_H(1)); -		rd32(hw, I40E_PRTTSYN_RXTIME_H(2)); -		rd32(hw, I40E_PRTTSYN_RXTIME_H(3)); -		pf->last_rx_ptp_check = jiffies; -		pf->rx_hwtstamp_cleared++; -		WARN_ONCE(1, "Detected Rx timestamp register hang\n"); -	} +	spin_unlock_bh(&pf->ptp_rx_lock);  }  /** @@ -353,14 +376,25 @@ void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index)  	hw = &pf->hw; -	prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1); +	spin_lock_bh(&pf->ptp_rx_lock); -	if (!(prttsyn_stat & BIT(index))) +	/* Get current Rx events and update latch times */ +	prttsyn_stat = i40e_ptp_get_rx_events(pf); + +	/* TODO: Should we warn about missing Rx timestamp event? */ +	if (!(prttsyn_stat & BIT(index))) { +		spin_unlock_bh(&pf->ptp_rx_lock);  		return; +	} + +	/* Clear the latched event since we're about to read its register */ +	pf->latch_event_flags &= ~BIT(index);  	lo = rd32(hw, I40E_PRTTSYN_RXTIME_L(index));  	hi = rd32(hw, I40E_PRTTSYN_RXTIME_H(index)); +	spin_unlock_bh(&pf->ptp_rx_lock); +  	ns = (((u64)hi) << 32) | lo;  	i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns); @@ -487,6 +521,8 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,  	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:  	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:  	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: +		if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE)) +			return -ERANGE;  		pf->ptp_rx = true;  		tsyntype = I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK |  			   I40E_PRTTSYN_CTL1_TSYNTYPE_V1 | @@ -494,19 +530,26 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,  		config->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;  		break;  	case HWTSTAMP_FILTER_PTP_V2_EVENT: -	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:  	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:  	case HWTSTAMP_FILTER_PTP_V2_SYNC: -	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:  	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:  	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: -	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:  	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: +		if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE)) +			return -ERANGE; +		/* fall through */ +	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: +	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: +	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:  		pf->ptp_rx = true;  		tsyntype = I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK | -			   I40E_PRTTSYN_CTL1_TSYNTYPE_V2 | -			   I40E_PRTTSYN_CTL1_UDP_ENA_MASK; -		config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; +			   I40E_PRTTSYN_CTL1_TSYNTYPE_V2; +		if (pf->flags & I40E_FLAG_PTP_L4_CAPABLE) { +			tsyntype |= I40E_PRTTSYN_CTL1_UDP_ENA_MASK; +			config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; +		} else { +			config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; +		}  		break;  	case HWTSTAMP_FILTER_ALL:  	default: @@ -514,12 +557,15 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,  	}  	/* Clear out all 1588-related registers to clear and unlatch them. */ +	spin_lock_bh(&pf->ptp_rx_lock);  	rd32(hw, I40E_PRTTSYN_STAT_0);  	rd32(hw, I40E_PRTTSYN_TXTIME_H);  	rd32(hw, I40E_PRTTSYN_RXTIME_H(0));  	rd32(hw, I40E_PRTTSYN_RXTIME_H(1));  	rd32(hw, I40E_PRTTSYN_RXTIME_H(2));  	rd32(hw, I40E_PRTTSYN_RXTIME_H(3)); +	pf->latch_event_flags = 0; +	spin_unlock_bh(&pf->ptp_rx_lock);  	/* Enable/disable the Tx timestamp interrupt based on user input. */  	regval = rd32(hw, I40E_PRTTSYN_CTL0); @@ -658,10 +704,8 @@ void i40e_ptp_init(struct i40e_pf *pf)  		return;  	} -	/* we have to initialize the lock first, since we can't control -	 * when the user will enter the PHC device entry points -	 */ -	spin_lock_init(&pf->tmreg_lock); +	mutex_init(&pf->tmreg_lock); +	spin_lock_init(&pf->ptp_rx_lock);  	/* ensure we have a clock device */  	err = i40e_ptp_create_clock(pf); diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 6287bf63c43c..352cf7cd2ef4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -122,14 +122,10 @@ static int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data,  	struct device *dev;  	dma_addr_t dma;  	u32 td_cmd = 0; -	u16 delay = 0;  	u16 i;  	/* find existing FDIR VSI */ -	vsi = NULL; -	for (i = 0; i < pf->num_alloc_vsi; i++) -		if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) -			vsi = pf->vsi[i]; +	vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR);  	if (!vsi)  		return -ENOENT; @@ -137,15 +133,11 @@ static int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data,  	dev = tx_ring->dev;  	/* we need two descriptors to add/del a filter and we can wait */ -	do { -		if (I40E_DESC_UNUSED(tx_ring) > 1) -			break; +	for (i = I40E_FD_CLEAN_DELAY; I40E_DESC_UNUSED(tx_ring) < 2; i--) { +		if (!i) +			return -EAGAIN;  		msleep_interruptible(1); -		delay++; -	} while (delay < I40E_FD_CLEAN_DELAY); - -	if (!(I40E_DESC_UNUSED(tx_ring) > 1)) -		return -EAGAIN; +	}  	dma = dma_map_single(dev, raw_packet,  			     I40E_FDIR_MAX_RAW_PACKET_SIZE, DMA_TO_DEVICE); @@ -335,22 +327,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,  	return err ? -EOPNOTSUPP : 0;  } -/** - * i40e_add_del_fdir_sctpv4 - Add/Remove SCTPv4 Flow Director filters for - * a specific flow spec - * @vsi: pointer to the targeted VSI - * @fd_data: the flow director data required for the FDir descriptor - * @add: true adds a filter, false removes it - * - * 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, -				    bool add) -{ -	return -EOPNOTSUPP; -} -  #define I40E_IP_DUMMY_PACKET_LEN 34  /**   * i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for @@ -433,12 +409,6 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,  	case UDP_V4_FLOW:  		ret = i40e_add_del_fdir_udpv4(vsi, input, add);  		break; -	case SCTP_V4_FLOW: -		ret = i40e_add_del_fdir_sctpv4(vsi, input, add); -		break; -	case IPV4_FLOW: -		ret = i40e_add_del_fdir_ipv4(vsi, input, add); -		break;  	case IP_USER_FLOW:  		switch (input->ip4_proto) {  		case IPPROTO_TCP: @@ -447,15 +417,16 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,  		case IPPROTO_UDP:  			ret = i40e_add_del_fdir_udpv4(vsi, input, add);  			break; -		case IPPROTO_SCTP: -			ret = i40e_add_del_fdir_sctpv4(vsi, input, add); -			break; -		default: +		case IPPROTO_IP:  			ret = i40e_add_del_fdir_ipv4(vsi, input, add);  			break; +		default: +			/* We cannot support masking based on protocol */ +			goto unsupported_flow;  		}  		break;  	default: +unsupported_flow:  		dev_info(&pf->pdev->dev, "Could not specify spec type %d\n",  			 input->flow_type);  		ret = -EINVAL; @@ -645,7 +616,7 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw)  	return 0;  } -#define WB_STRIDE 0x3 +#define WB_STRIDE 4  /**   * i40e_clean_tx_irq - Reclaim resources after transmit completes @@ -761,7 +732,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,  		unsigned int j = i40e_get_tx_pending(tx_ring, false);  		if (budget && -		    ((j / (WB_STRIDE + 1)) == 0) && (j != 0) && +		    ((j / WB_STRIDE) == 0) && (j > 0) &&  		    !test_bit(__I40E_DOWN, &vsi->state) &&  		    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))  			tx_ring->arm_wb = true; @@ -1246,7 +1217,6 @@ bool i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)  		 * because each write-back erases this info.  		 */  		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); -		rx_desc->read.hdr_addr = 0;  		rx_desc++;  		bi++; @@ -1437,13 +1407,12 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,  	u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);  	u32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>  			I40E_RXD_QW1_STATUS_SHIFT; -	u32 rsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >> +	u32 tsynvalid = rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK; +	u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>  		   I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT; -	if (unlikely(rsyn)) { -		i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, rsyn); -		rx_ring->last_rx_timestamp = jiffies; -	} +	if (unlikely(tsynvalid)) +		i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn);  	i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype); @@ -1767,7 +1736,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)  	while (likely(total_rx_packets < budget)) {  		union i40e_rx_desc *rx_desc;  		struct sk_buff *skb; -		u32 rx_status;  		u16 vlan_tag;  		u8 rx_ptype;  		u64 qword; @@ -1781,21 +1749,13 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)  		rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean); -		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); -		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> -			   I40E_RXD_QW1_PTYPE_SHIFT; -		rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >> -			    I40E_RXD_QW1_STATUS_SHIFT; - -		if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT))) -			break; -  		/* status_error_len will always be zero for unused descriptors  		 * because it's cleared in cleanup, and overlaps with hdr_addr  		 * which is always zero because packet split isn't used, if the  		 * hardware wrote DD then it will be non-zero  		 */ -		if (!rx_desc->wb.qword1.status_error_len) +		if (!i40e_test_staterr(rx_desc, +				       BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))  			break;  		/* This memory barrier is needed to keep us from reading @@ -1829,6 +1789,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)  		/* probably a little skewed due to removing CRC */  		total_rx_bytes += skb->len; +		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); +		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> +			   I40E_RXD_QW1_PTYPE_SHIFT; +  		/* populate checksum, VLAN, and protocol */  		i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype); @@ -2025,12 +1989,25 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)  	/* If work not completed, return budget and polling will return */  	if (!clean_complete) { +		const cpumask_t *aff_mask = &q_vector->affinity_mask; +		int cpu_id = smp_processor_id(); + +		/* It is possible that the interrupt affinity has changed but, +		 * if the cpu is pegged at 100%, polling will never exit while +		 * traffic continues and the interrupt will be stuck on this +		 * cpu.  We check to make sure affinity is correct before we +		 * continue to poll, otherwise we must stop polling so the +		 * interrupt can move to the correct cpu. +		 */ +		if (likely(cpumask_test_cpu(cpu_id, aff_mask) || +			   !(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))) {  tx_only: -		if (arm_wb) { -			q_vector->tx.ring[0].tx_stats.tx_force_wb++; -			i40e_enable_wb_on_itr(vsi, q_vector); +			if (arm_wb) { +				q_vector->tx.ring[0].tx_stats.tx_force_wb++; +				i40e_enable_wb_on_itr(vsi, q_vector); +			} +			return budget;  		} -		return budget;  	}  	if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR) @@ -2038,12 +2015,19 @@ tx_only:  	/* Work is done so exit the polling mode and re-enable the interrupt */  	napi_complete_done(napi, work_done); -	if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) { -		i40e_update_enable_itr(vsi, q_vector); -	} else { /* Legacy mode */ + +	/* If we're prematurely stopping polling to fix the interrupt +	 * affinity we want to make sure polling starts back up so we +	 * issue a call to i40e_force_wb which triggers a SW interrupt. +	 */ +	if (!clean_complete) +		i40e_force_wb(vsi, q_vector); +	else if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))  		i40e_irq_dynamic_enable_icr0(vsi->back, false); -	} -	return 0; +	else +		i40e_update_enable_itr(vsi, q_vector); + +	return min(work_done, budget - 1);  }  /** @@ -2716,9 +2700,7 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,  	u32 td_tag = 0;  	dma_addr_t dma;  	u16 gso_segs; -	u16 desc_count = 0; -	bool tail_bump = true; -	bool do_rs = false; +	u16 desc_count = 1;  	if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {  		td_cmd |= I40E_TX_DESC_CMD_IL2TAG1; @@ -2801,8 +2783,7 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,  		tx_bi = &tx_ring->tx_bi[i];  	} -	/* set next_to_watch value indicating a packet is present */ -	first->next_to_watch = tx_desc; +	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);  	i++;  	if (i == tx_ring->count) @@ -2810,66 +2791,72 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,  	tx_ring->next_to_use = i; -	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);  	i40e_maybe_stop_tx(tx_ring, DESC_NEEDED); +	/* write last descriptor with EOP bit */ +	td_cmd |= I40E_TX_DESC_CMD_EOP; + +	/* We can OR these values together as they both are checked against +	 * 4 below and at this point desc_count will be used as a boolean value +	 * after this if/else block. +	 */ +	desc_count |= ++tx_ring->packet_stride; +  	/* Algorithm to optimize tail and RS bit setting: -	 * if xmit_more is supported -	 *	if xmit_more is true -	 *		do not update tail and do not mark RS bit. -	 *	if xmit_more is false and last xmit_more was false -	 *		if every packet spanned less than 4 desc -	 *			then set RS bit on 4th packet and update tail -	 *			on every packet -	 *		else -	 *			update tail and set RS bit on every packet. -	 *	if xmit_more is false and last_xmit_more was true -	 *		update tail and set RS bit. +	 * if queue is stopped +	 *	mark RS bit +	 *	reset packet counter +	 * else if xmit_more is supported and is true +	 *	advance packet counter to 4 +	 *	reset desc_count to 0  	 * -	 * Optimization: wmb to be issued only in case of tail update. -	 * Also optimize the Descriptor WB path for RS bit with the same -	 * algorithm. +	 * if desc_count >= 4 +	 *	mark RS bit +	 *	reset packet counter +	 * if desc_count > 0 +	 *	update tail  	 * -	 * Note: If there are less than 4 packets +	 * Note: If there are less than 4 descriptors  	 * pending and interrupts were disabled the service task will  	 * trigger a force WB.  	 */ -	if (skb->xmit_more  && -	    !netif_xmit_stopped(txring_txq(tx_ring))) { -		tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; -		tail_bump = false; -	} else if (!skb->xmit_more && -		   !netif_xmit_stopped(txring_txq(tx_ring)) && -		   (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) && -		   (tx_ring->packet_stride < WB_STRIDE) && -		   (desc_count < WB_STRIDE)) { -		tx_ring->packet_stride++; -	} else { +	if (netif_xmit_stopped(txring_txq(tx_ring))) { +		goto do_rs; +	} else if (skb->xmit_more) { +		/* set stride to arm on next packet and reset desc_count */ +		tx_ring->packet_stride = WB_STRIDE; +		desc_count = 0; +	} else if (desc_count >= WB_STRIDE) { +do_rs: +		/* write last descriptor with RS bit set */ +		td_cmd |= I40E_TX_DESC_CMD_RS;  		tx_ring->packet_stride = 0; -		tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; -		do_rs = true;  	} -	if (do_rs) -		tx_ring->packet_stride = 0;  	tx_desc->cmd_type_offset_bsz = -			build_ctob(td_cmd, td_offset, size, td_tag) | -			cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD : -						  I40E_TX_DESC_CMD_EOP) << -						  I40E_TXD_QW1_CMD_SHIFT); +			build_ctob(td_cmd, td_offset, size, td_tag); + +	/* Force memory writes to complete before letting h/w know there +	 * are new descriptors to fetch. +	 * +	 * We also use this memory barrier to make certain all of the +	 * status bits have been updated before next_to_watch is written. +	 */ +	wmb(); + +	/* set next_to_watch value indicating a packet is present */ +	first->next_to_watch = tx_desc;  	/* notify HW of packet */ -	if (!tail_bump) { -		prefetchw(tx_desc + 1); -	} else { -		/* Force memory writes to complete before letting h/w -		 * know there are new descriptors to fetch.  (Only -		 * applicable for weak-ordered memory model archs, -		 * such as IA-64). -		 */ -		wmb(); +	if (desc_count) {  		writel(i, tx_ring->tail); + +		/* we need this if more than one processor can write to our tail +		 * at a time, it synchronizes IO on IA64/Altix systems +		 */ +		mmiowb();  	} +  	return;  dma_error: diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 508840585645..e065321ce8ed 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -173,26 +173,37 @@ static inline bool i40e_test_staterr(union i40e_rx_desc *rx_desc,  #define I40E_MAX_DATA_PER_TXD_ALIGNED \  	(I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1)) -/* This ugly bit of math is equivalent to DIV_ROUNDUP(size, X) where X is - * the value I40E_MAX_DATA_PER_TXD_ALIGNED.  It is needed due to the fact - * that 12K is not a power of 2 and division is expensive.  It is used to - * approximate the number of descriptors used per linear buffer.  Note - * that this will overestimate in some cases as it doesn't account for the - * fact that we will add up to 4K - 1 in aligning the 12K buffer, however - * the error should not impact things much as large buffers usually mean - * we will use fewer descriptors then there are frags in an skb. +/** + * i40e_txd_use_count  - estimate the number of descriptors needed for Tx + * @size: transmit request size in bytes + * + * Due to hardware alignment restrictions (4K alignment), we need to + * assume that we can have no more than 12K of data per descriptor, even + * though each descriptor can take up to 16K - 1 bytes of aligned memory. + * Thus, we need to divide by 12K. But division is slow! Instead, + * we decompose the operation into shifts and one relatively cheap + * multiply operation. + * + * To divide by 12K, we first divide by 4K, then divide by 3: + *     To divide by 4K, shift right by 12 bits + *     To divide by 3, multiply by 85, then divide by 256 + *     (Divide by 256 is done by shifting right by 8 bits) + * Finally, we add one to round up. Because 256 isn't an exact multiple of + * 3, we'll underestimate near each multiple of 12K. This is actually more + * accurate as we have 4K - 1 of wiggle room that we can fit into the last + * segment.  For our purposes this is accurate out to 1M which is orders of + * magnitude greater than our largest possible GSO size. + * + * This would then be implemented as: + *     return (((size >> 12) * 85) >> 8) + 1; + * + * Since multiplication and division are commutative, we can reorder + * operations into: + *     return ((size * 85) >> 20) + 1;   */  static inline unsigned int i40e_txd_use_count(unsigned int size)  { -	const unsigned int max = I40E_MAX_DATA_PER_TXD_ALIGNED; -	const unsigned int reciprocal = ((1ull << 32) - 1 + (max / 2)) / max; -	unsigned int adjust = ~(u32)0; - -	/* if we rounded up on the reciprocal pull down the adjustment */ -	if ((max * reciprocal) > adjust) -		adjust = ~(u32)(reciprocal - 1); - -	return (u32)((((u64)size * reciprocal) + adjust) >> 32); +	return ((size * 85) >> 20) + 1;  }  /* Tx Descriptors needed, worst case */ @@ -307,15 +318,12 @@ struct i40e_ring {  	u8 atr_sample_rate;  	u8 atr_count; -	unsigned long last_rx_timestamp; -  	bool ring_active;		/* is ring online or not */  	bool arm_wb;		/* do something to arm write back */  	u8 packet_stride;  	u16 flags;  #define I40E_TXR_FLAGS_WB_ON_ITR	BIT(0) -#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)  	/* stats structs */  	struct i40e_queue_stats	stats; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index bd5f13bef83c..edc0abdf4783 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -90,14 +90,23 @@ enum i40e_debug_mask {  	I40E_DEBUG_ALL			= 0xFFFFFFFF  }; -#define I40E_MDIO_STCODE                0 -#define I40E_MDIO_OPCODE_ADDRESS        0 -#define I40E_MDIO_OPCODE_WRITE          I40E_MASK(1, \ +#define I40E_MDIO_CLAUSE22_STCODE_MASK	I40E_MASK(1, \ +						  I40E_GLGEN_MSCA_STCODE_SHIFT) +#define I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK	I40E_MASK(1, \  						  I40E_GLGEN_MSCA_OPCODE_SHIFT) -#define I40E_MDIO_OPCODE_READ_INC_ADDR  I40E_MASK(2, \ +#define I40E_MDIO_CLAUSE22_OPCODE_READ_MASK	I40E_MASK(2, \  						  I40E_GLGEN_MSCA_OPCODE_SHIFT) -#define I40E_MDIO_OPCODE_READ           I40E_MASK(3, \ + +#define I40E_MDIO_CLAUSE45_STCODE_MASK	I40E_MASK(0, \ +						  I40E_GLGEN_MSCA_STCODE_SHIFT) +#define I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK	I40E_MASK(0, \ +						  I40E_GLGEN_MSCA_OPCODE_SHIFT) +#define I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK	I40E_MASK(1, \  						  I40E_GLGEN_MSCA_OPCODE_SHIFT) +#define I40E_MDIO_CLAUSE45_OPCODE_READ_INC_ADDR_MASK	I40E_MASK(2, \ +						I40E_GLGEN_MSCA_OPCODE_SHIFT) +#define I40E_MDIO_CLAUSE45_OPCODE_READ_MASK	I40E_MASK(3, \ +						I40E_GLGEN_MSCA_OPCODE_SHIFT)  #define I40E_PHY_COM_REG_PAGE                   0x1E  #define I40E_PHY_LED_LINK_MODE_MASK             0xF0 @@ -204,47 +213,59 @@ struct i40e_link_status {  #define I40E_MODULE_TYPE_1000BASE_T	0x08  }; -enum i40e_aq_capabilities_phy_type { -	I40E_CAP_PHY_TYPE_SGMII		  = BIT(I40E_PHY_TYPE_SGMII), -	I40E_CAP_PHY_TYPE_1000BASE_KX	  = BIT(I40E_PHY_TYPE_1000BASE_KX), -	I40E_CAP_PHY_TYPE_10GBASE_KX4	  = BIT(I40E_PHY_TYPE_10GBASE_KX4), -	I40E_CAP_PHY_TYPE_10GBASE_KR	  = BIT(I40E_PHY_TYPE_10GBASE_KR), -	I40E_CAP_PHY_TYPE_40GBASE_KR4	  = BIT(I40E_PHY_TYPE_40GBASE_KR4), -	I40E_CAP_PHY_TYPE_XAUI		  = BIT(I40E_PHY_TYPE_XAUI), -	I40E_CAP_PHY_TYPE_XFI		  = BIT(I40E_PHY_TYPE_XFI), -	I40E_CAP_PHY_TYPE_SFI		  = BIT(I40E_PHY_TYPE_SFI), -	I40E_CAP_PHY_TYPE_XLAUI		  = BIT(I40E_PHY_TYPE_XLAUI), -	I40E_CAP_PHY_TYPE_XLPPI		  = BIT(I40E_PHY_TYPE_XLPPI), -	I40E_CAP_PHY_TYPE_40GBASE_CR4_CU  = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU), -	I40E_CAP_PHY_TYPE_10GBASE_CR1_CU  = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU), -	I40E_CAP_PHY_TYPE_10GBASE_AOC	  = BIT(I40E_PHY_TYPE_10GBASE_AOC), -	I40E_CAP_PHY_TYPE_40GBASE_AOC	  = BIT(I40E_PHY_TYPE_40GBASE_AOC), -	I40E_CAP_PHY_TYPE_100BASE_TX	  = BIT(I40E_PHY_TYPE_100BASE_TX), -	I40E_CAP_PHY_TYPE_1000BASE_T	  = BIT(I40E_PHY_TYPE_1000BASE_T), -	I40E_CAP_PHY_TYPE_10GBASE_T	  = BIT(I40E_PHY_TYPE_10GBASE_T), -	I40E_CAP_PHY_TYPE_10GBASE_SR	  = BIT(I40E_PHY_TYPE_10GBASE_SR), -	I40E_CAP_PHY_TYPE_10GBASE_LR	  = BIT(I40E_PHY_TYPE_10GBASE_LR), -	I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU), -	I40E_CAP_PHY_TYPE_10GBASE_CR1	  = BIT(I40E_PHY_TYPE_10GBASE_CR1), -	I40E_CAP_PHY_TYPE_40GBASE_CR4	  = BIT(I40E_PHY_TYPE_40GBASE_CR4), -	I40E_CAP_PHY_TYPE_40GBASE_SR4	  = BIT(I40E_PHY_TYPE_40GBASE_SR4), -	I40E_CAP_PHY_TYPE_40GBASE_LR4	  = BIT(I40E_PHY_TYPE_40GBASE_LR4), -	I40E_CAP_PHY_TYPE_1000BASE_SX	  = BIT(I40E_PHY_TYPE_1000BASE_SX), -	I40E_CAP_PHY_TYPE_1000BASE_LX	  = BIT(I40E_PHY_TYPE_1000BASE_LX), -	I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL = -					 BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL), -	I40E_CAP_PHY_TYPE_20GBASE_KR2	  = BIT(I40E_PHY_TYPE_20GBASE_KR2) -}; -  struct i40e_phy_info {  	struct i40e_link_status link_info;  	struct i40e_link_status link_info_old;  	bool get_link_info;  	enum i40e_media_type media_type;  	/* all the phy types the NVM is capable of */ -	enum i40e_aq_capabilities_phy_type phy_types; -}; - +	u64 phy_types; +}; + +#define I40E_CAP_PHY_TYPE_SGMII BIT_ULL(I40E_PHY_TYPE_SGMII) +#define I40E_CAP_PHY_TYPE_1000BASE_KX BIT_ULL(I40E_PHY_TYPE_1000BASE_KX) +#define I40E_CAP_PHY_TYPE_10GBASE_KX4 BIT_ULL(I40E_PHY_TYPE_10GBASE_KX4) +#define I40E_CAP_PHY_TYPE_10GBASE_KR BIT_ULL(I40E_PHY_TYPE_10GBASE_KR) +#define I40E_CAP_PHY_TYPE_40GBASE_KR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_KR4) +#define I40E_CAP_PHY_TYPE_XAUI BIT_ULL(I40E_PHY_TYPE_XAUI) +#define I40E_CAP_PHY_TYPE_XFI BIT_ULL(I40E_PHY_TYPE_XFI) +#define I40E_CAP_PHY_TYPE_SFI BIT_ULL(I40E_PHY_TYPE_SFI) +#define I40E_CAP_PHY_TYPE_XLAUI BIT_ULL(I40E_PHY_TYPE_XLAUI) +#define I40E_CAP_PHY_TYPE_XLPPI BIT_ULL(I40E_PHY_TYPE_XLPPI) +#define I40E_CAP_PHY_TYPE_40GBASE_CR4_CU BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4_CU) +#define I40E_CAP_PHY_TYPE_10GBASE_CR1_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1_CU) +#define I40E_CAP_PHY_TYPE_10GBASE_AOC BIT_ULL(I40E_PHY_TYPE_10GBASE_AOC) +#define I40E_CAP_PHY_TYPE_40GBASE_AOC BIT_ULL(I40E_PHY_TYPE_40GBASE_AOC) +#define I40E_CAP_PHY_TYPE_100BASE_TX BIT_ULL(I40E_PHY_TYPE_100BASE_TX) +#define I40E_CAP_PHY_TYPE_1000BASE_T BIT_ULL(I40E_PHY_TYPE_1000BASE_T) +#define I40E_CAP_PHY_TYPE_10GBASE_T BIT_ULL(I40E_PHY_TYPE_10GBASE_T) +#define I40E_CAP_PHY_TYPE_10GBASE_SR BIT_ULL(I40E_PHY_TYPE_10GBASE_SR) +#define I40E_CAP_PHY_TYPE_10GBASE_LR BIT_ULL(I40E_PHY_TYPE_10GBASE_LR) +#define I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_SFPP_CU) +#define I40E_CAP_PHY_TYPE_10GBASE_CR1 BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1) +#define I40E_CAP_PHY_TYPE_40GBASE_CR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4) +#define I40E_CAP_PHY_TYPE_40GBASE_SR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_SR4) +#define I40E_CAP_PHY_TYPE_40GBASE_LR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_LR4) +#define I40E_CAP_PHY_TYPE_1000BASE_SX BIT_ULL(I40E_PHY_TYPE_1000BASE_SX) +#define I40E_CAP_PHY_TYPE_1000BASE_LX BIT_ULL(I40E_PHY_TYPE_1000BASE_LX) +#define I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL \ +				BIT_ULL(I40E_PHY_TYPE_1000BASE_T_OPTICAL) +#define I40E_CAP_PHY_TYPE_20GBASE_KR2 BIT_ULL(I40E_PHY_TYPE_20GBASE_KR2) +/* Defining the macro I40E_TYPE_OFFSET to implement a bit shift for some + * PHY types. There is an unused bit (31) in the I40E_CAP_PHY_TYPE_* bit + * fields but no corresponding gap in the i40e_aq_phy_type enumeration. So, + * a shift is needed to adjust for this with values larger than 31. The + * only affected values are I40E_PHY_TYPE_25GBASE_*. + */ +#define I40E_PHY_TYPE_OFFSET 1 +#define I40E_CAP_PHY_TYPE_25GBASE_KR BIT_ULL(I40E_PHY_TYPE_25GBASE_KR + \ +					     I40E_PHY_TYPE_OFFSET) +#define I40E_CAP_PHY_TYPE_25GBASE_CR BIT_ULL(I40E_PHY_TYPE_25GBASE_CR + \ +					     I40E_PHY_TYPE_OFFSET) +#define I40E_CAP_PHY_TYPE_25GBASE_SR BIT_ULL(I40E_PHY_TYPE_25GBASE_SR + \ +					     I40E_PHY_TYPE_OFFSET) +#define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \ +					     I40E_PHY_TYPE_OFFSET)  #define I40E_HW_CAP_MAX_GPIO			30  /* Capabilities of a PF or a VF or the whole device */  struct i40e_hw_capabilities { @@ -254,6 +275,10 @@ struct i40e_hw_capabilities {  #define I40E_NVM_IMAGE_TYPE_UDP_CLOUD	0x3  	u32  management_mode; +	u32  mng_protocols_over_mctp; +#define I40E_MNG_PROTOCOL_PLDM		0x2 +#define I40E_MNG_PROTOCOL_OEM_COMMANDS	0x4 +#define I40E_MNG_PROTOCOL_NCSI		0x8  	u32  npar_enable;  	u32  os2bmc;  	u32  valid_functions; @@ -366,6 +391,7 @@ enum i40e_nvmupd_state {  	I40E_NVMUPD_STATE_WRITING,  	I40E_NVMUPD_STATE_INIT_WAIT,  	I40E_NVMUPD_STATE_WRITE_WAIT, +	I40E_NVMUPD_STATE_ERROR  };  /* nvm_access definition and its masks/shifts need to be accessible to diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h index f861d3109d1a..974ba2baf6ea 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h @@ -165,6 +165,10 @@ struct i40e_virtchnl_vsi_resource {  #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF		0X00080000  #define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM	0X00100000 +#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \ +				    I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \ +				    I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) +  struct i40e_virtchnl_vf_resource {  	u16 num_vsis;  	u16 num_queue_pairs; diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 54b8ee2583f1..a6198b727e24 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -674,6 +674,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)  	}  	if (type == I40E_VSI_SRIOV) {  		u64 hena = i40e_pf_get_default_rss_hena(pf); +		u8 broadcast[ETH_ALEN];  		vf->lan_vsi_idx = vsi->idx;  		vf->lan_vsi_id = vsi->id; @@ -686,17 +687,23 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)  		if (vf->port_vlan_id)  			i40e_vsi_add_pvid(vsi, vf->port_vlan_id); -		spin_lock_bh(&vsi->mac_filter_list_lock); +		spin_lock_bh(&vsi->mac_filter_hash_lock);  		if (is_valid_ether_addr(vf->default_lan_addr.addr)) {  			f = i40e_add_filter(vsi, vf->default_lan_addr.addr, -				       vf->port_vlan_id ? vf->port_vlan_id : -1, -				       true, false); +				       vf->port_vlan_id ? +				       vf->port_vlan_id : -1);  			if (!f)  				dev_info(&pf->pdev->dev,  					 "Could not add MAC filter %pM for VF %d\n",  					vf->default_lan_addr.addr, vf->vf_id);  		} -		spin_unlock_bh(&vsi->mac_filter_list_lock); +		eth_broadcast_addr(broadcast); +		f = i40e_add_filter(vsi, broadcast, +				    vf->port_vlan_id ? vf->port_vlan_id : -1); +		if (!f) +			dev_info(&pf->pdev->dev, +				 "Could not allocate VF broadcast filter\n"); +		spin_unlock_bh(&vsi->mac_filter_hash_lock);  		i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(0, vf->vf_id),  				  (u32)hena);  		i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(1, vf->vf_id), @@ -811,6 +818,7 @@ static void i40e_free_vf_res(struct i40e_vf *vf)  		i40e_vsi_release(pf->vsi[vf->lan_vsi_idx]);  		vf->lan_vsi_idx = 0;  		vf->lan_vsi_id = 0; +		vf->num_mac = 0;  	}  	msix_vf = pf->hw.func_caps.num_msix_vectors_vf; @@ -990,7 +998,7 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)  	if (vf->lan_vsi_idx == 0)  		goto complete_reset; -	i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false); +	i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);  complete_reset:  	/* reallocate VF resources to reset the VSI state */  	i40e_free_vf_res(vf); @@ -1031,8 +1039,7 @@ void i40e_free_vfs(struct i40e_pf *pf)  	i40e_notify_client_of_vf_enable(pf, 0);  	for (i = 0; i < pf->num_alloc_vfs; i++)  		if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states)) -			i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx], -					       false); +			i40e_vsi_stop_rings(pf->vsi[pf->vf[i].lan_vsi_idx]);  	/* Disable IOV before freeing resources. This lets any VF drivers  	 * running in the host get themselves cleaned up before we yank @@ -1449,9 +1456,9 @@ static void i40e_vc_reset_vf_msg(struct i40e_vf *vf)  static inline int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)  {  	struct i40e_mac_filter *f; -	int num_vlans = 0; +	int num_vlans = 0, bkt; -	list_for_each_entry(f, &vsi->mac_filter_list, list) { +	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {  		if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID)  			num_vlans++;  	} @@ -1481,6 +1488,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,  	struct i40e_vsi *vsi;  	bool alluni = false;  	int aq_err = 0; +	int bkt;  	vsi = i40e_find_vsi_from_id(pf, info->vsi_id);  	if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || @@ -1507,7 +1515,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,  							    vf->port_vlan_id,  							    NULL);  	} else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) { -		list_for_each_entry(f, &vsi->mac_filter_list, list) { +		hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {  			if (f->vlan < 0 || f->vlan > I40E_MAX_VLANID)  				continue;  			aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw, @@ -1535,7 +1543,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,  				vf->vf_id,  				i40e_stat_str(&pf->hw, aq_ret),  				i40e_aq_str(&pf->hw, aq_err)); -			goto error_param_int; +			goto error_param;  		}  	} @@ -1557,7 +1565,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,  							    vf->port_vlan_id,  							    NULL);  	} else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) { -		list_for_each_entry(f, &vsi->mac_filter_list, list) { +		hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {  			aq_ret = 0;  			if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID) {  				aq_ret = @@ -1580,15 +1588,16 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,  							     allmulti, NULL,  							     true);  		aq_err = pf->hw.aq.asq_last_status; -		if (aq_ret) +		if (aq_ret) {  			dev_err(&pf->pdev->dev,  				"VF %d failed to set unicast promiscuous mode %8.8x err %s aq_err %s\n",  				vf->vf_id, info->flags,  				i40e_stat_str(&pf->hw, aq_ret),  				i40e_aq_str(&pf->hw, aq_err)); +			goto error_param; +		}  	} -error_param_int:  	if (!aq_ret) {  		dev_info(&pf->pdev->dev,  			 "VF %d successfully set unicast promiscuous mode\n", @@ -1757,7 +1766,7 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)  		goto error_param;  	} -	if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], true)) +	if (i40e_vsi_start_rings(pf->vsi[vf->lan_vsi_idx]))  		aq_ret = I40E_ERR_TIMEOUT;  error_param:  	/* send the response to the VF */ @@ -1796,8 +1805,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)  		goto error_param;  	} -	if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false)) -		aq_ret = I40E_ERR_TIMEOUT; +	i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);  error_param:  	/* send the response to the VF */ @@ -1927,20 +1935,18 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)  	/* Lock once, because all function inside for loop accesses VSI's  	 * MAC filter list which needs to be protected using same lock.  	 */ -	spin_lock_bh(&vsi->mac_filter_list_lock); +	spin_lock_bh(&vsi->mac_filter_hash_lock);  	/* add new addresses to the list */  	for (i = 0; i < al->num_elements; i++) {  		struct i40e_mac_filter *f; -		f = i40e_find_mac(vsi, al->list[i].addr, true, false); +		f = i40e_find_mac(vsi, al->list[i].addr);  		if (!f) {  			if (i40e_is_vsi_in_vlan(vsi)) -				f = i40e_put_mac_in_vlan(vsi, al->list[i].addr, -							 true, false); +				f = i40e_put_mac_in_vlan(vsi, al->list[i].addr);  			else -				f = i40e_add_filter(vsi, al->list[i].addr, -1, -						    true, false); +				f = i40e_add_filter(vsi, al->list[i].addr, -1);  		}  		if (!f) { @@ -1948,13 +1954,13 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)  				"Unable to add MAC filter %pM for VF %d\n",  				 al->list[i].addr, vf->vf_id);  			ret = I40E_ERR_PARAM; -			spin_unlock_bh(&vsi->mac_filter_list_lock); +			spin_unlock_bh(&vsi->mac_filter_hash_lock);  			goto error_param;  		} else {  			vf->num_mac++;  		}  	} -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	/* program the updated filter list */  	ret = i40e_sync_vsi_filters(vsi); @@ -2003,18 +2009,18 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)  	}  	vsi = pf->vsi[vf->lan_vsi_idx]; -	spin_lock_bh(&vsi->mac_filter_list_lock); +	spin_lock_bh(&vsi->mac_filter_hash_lock);  	/* delete addresses from the list */  	for (i = 0; i < al->num_elements; i++) -		if (i40e_del_mac_all_vlan(vsi, al->list[i].addr, true, false)) { +		if (i40e_del_mac_all_vlan(vsi, al->list[i].addr)) {  			ret = I40E_ERR_INVALID_MAC_ADDR; -			spin_unlock_bh(&vsi->mac_filter_list_lock); +			spin_unlock_bh(&vsi->mac_filter_hash_lock);  			goto error_param;  		} else {  			vf->num_mac--;  		} -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	/* program the updated filter list */  	ret = i40e_sync_vsi_filters(vsi); @@ -2139,9 +2145,8 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)  	}  	for (i = 0; i < vfl->num_elements; i++) { -		int ret = i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]); -		if (!ret) -			vf->num_vlan--; +		i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]); +		vf->num_vlan--;  		if (test_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states))  			i40e_aq_set_vsi_uc_promisc_on_vlan(&pf->hw, vsi->seid, @@ -2153,11 +2158,6 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)  							   false,  							   vfl->vlan_id[i],  							   NULL); - -		if (ret) -			dev_err(&pf->pdev->dev, -				"Unable to delete VLAN filter %d for VF %d, error %d\n", -				vfl->vlan_id[i], vf->vf_id, ret);  	}  error_param: @@ -2689,6 +2689,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)  	struct i40e_mac_filter *f;  	struct i40e_vf *vf;  	int ret = 0; +	int bkt;  	/* validate the request */  	if (vf_id >= pf->num_alloc_vfs) { @@ -2715,23 +2716,22 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)  	}  	/* Lock once because below invoked function add/del_filter requires -	 * mac_filter_list_lock to be held +	 * mac_filter_hash_lock to be held  	 */ -	spin_lock_bh(&vsi->mac_filter_list_lock); +	spin_lock_bh(&vsi->mac_filter_hash_lock);  	/* delete the temporary mac address */  	if (!is_zero_ether_addr(vf->default_lan_addr.addr))  		i40e_del_filter(vsi, vf->default_lan_addr.addr, -				vf->port_vlan_id ? vf->port_vlan_id : -1, -				true, false); +				vf->port_vlan_id ? vf->port_vlan_id : -1);  	/* Delete all the filters for this VSI - we're going to kill it  	 * anyway.  	 */ -	list_for_each_entry(f, &vsi->mac_filter_list, list) -		i40e_del_filter(vsi, f->macaddr, f->vlan, true, false); +	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) +		i40e_del_filter(vsi, f->macaddr, f->vlan); -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id);  	/* program mac filter */ @@ -2766,7 +2766,6 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,  	u16 vlanprio = vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT);  	struct i40e_netdev_priv *np = netdev_priv(netdev);  	struct i40e_pf *pf = np->vsi->back; -	bool is_vsi_in_vlan = false;  	struct i40e_vsi *vsi;  	struct i40e_vf *vf;  	int ret = 0; @@ -2803,11 +2802,10 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,  		/* duplicate request, so just return success */  		goto error_pvid; -	spin_lock_bh(&vsi->mac_filter_list_lock); -	is_vsi_in_vlan = i40e_is_vsi_in_vlan(vsi); -	spin_unlock_bh(&vsi->mac_filter_list_lock); +	/* Locked once because multiple functions below iterate list */ +	spin_lock_bh(&vsi->mac_filter_hash_lock); -	if (le16_to_cpu(vsi->info.pvid) == 0 && is_vsi_in_vlan) { +	if (le16_to_cpu(vsi->info.pvid) == 0 && i40e_is_vsi_in_vlan(vsi)) {  		dev_err(&pf->pdev->dev,  			"VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n",  			vf_id); @@ -2830,19 +2828,23 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,  	 */  	if ((!(vlan_id || qos) ||  	    vlanprio != le16_to_cpu(vsi->info.pvid)) && -	    vsi->info.pvid) -		ret = i40e_vsi_add_vlan(vsi, I40E_VLAN_ANY); - -	if (vsi->info.pvid) { -		/* kill old VLAN */ -		ret = i40e_vsi_kill_vlan(vsi, (le16_to_cpu(vsi->info.pvid) & -					       VLAN_VID_MASK)); +	    vsi->info.pvid) { +		ret = i40e_add_vlan_all_mac(vsi, I40E_VLAN_ANY);  		if (ret) {  			dev_info(&vsi->back->pdev->dev, -				 "remove VLAN failed, ret=%d, aq_err=%d\n", -				 ret, pf->hw.aq.asq_last_status); +				 "add VF VLAN failed, ret=%d aq_err=%d\n", ret, +				 vsi->back->hw.aq.asq_last_status); +			spin_unlock_bh(&vsi->mac_filter_hash_lock); +			goto error_pvid;  		}  	} + +	if (vsi->info.pvid) { +		/* remove all filters on the old VLAN */ +		i40e_rm_vlan_all_mac(vsi, (le16_to_cpu(vsi->info.pvid) & +					   VLAN_VID_MASK)); +	} +  	if (vlan_id || qos)  		ret = i40e_vsi_add_pvid(vsi, vlanprio);  	else @@ -2852,24 +2854,30 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,  		dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",  			 vlan_id, qos, vf_id); -		/* add new VLAN filter */ -		ret = i40e_vsi_add_vlan(vsi, vlan_id); +		/* add new VLAN filter for each MAC */ +		ret = i40e_add_vlan_all_mac(vsi, vlan_id);  		if (ret) {  			dev_info(&vsi->back->pdev->dev,  				 "add VF VLAN failed, ret=%d aq_err=%d\n", ret,  				 vsi->back->hw.aq.asq_last_status); +			spin_unlock_bh(&vsi->mac_filter_hash_lock);  			goto error_pvid;  		} -		/* Kill non-vlan MAC filters - ignore error return since -		 * there might not be any non-vlan MAC filters. -		 */ -		i40e_vsi_kill_vlan(vsi, I40E_VLAN_ANY); + +		/* remove the previously added non-VLAN MAC filters */ +		i40e_rm_vlan_all_mac(vsi, I40E_VLAN_ANY);  	} +	spin_unlock_bh(&vsi->mac_filter_hash_lock); + +	/* Schedule the worker thread to take care of applying changes */ +	i40e_service_event_schedule(vsi->back); +  	if (ret) {  		dev_err(&pf->pdev->dev, "Unable to update VF vsi context\n");  		goto error_pvid;  	} +  	/* The Port VLAN needs to be saved across resets the same as the  	 * default LAN MAC address.  	 */ @@ -2926,6 +2934,9 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,  	case I40E_LINK_SPEED_40GB:  		speed = 40000;  		break; +	case I40E_LINK_SPEED_25GB: +		speed = 25000; +		break;  	case I40E_LINK_SPEED_20GB:  		speed = 20000;  		break; @@ -2940,7 +2951,7 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,  	}  	if (max_tx_rate > speed) { -		dev_err(&pf->pdev->dev, "Invalid max tx rate %d specified for VF %d.", +		dev_err(&pf->pdev->dev, "Invalid max tx rate %d specified for VF %d.\n",  			max_tx_rate, vf->vf_id);  		ret = -EINVAL;  		goto error; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index 44f7ed7583dd..96385156b824 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -912,11 +912,11 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,  	desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);  	desc_idx = ntc; +	hw->aq.arq_last_status = +		(enum i40e_admin_queue_err)le16_to_cpu(desc->retval);  	flags = le16_to_cpu(desc->flags);  	if (flags & I40E_AQ_FLAG_ERR) {  		ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; -		hw->aq.arq_last_status = -			(enum i40e_admin_queue_err)le16_to_cpu(desc->retval);  		i40e_debug(hw,  			   I40E_DEBUG_AQ_MESSAGE,  			   "AQRX: Event received with error 0x%X.\n", diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 40b0eafd0c71..eeb9864bc5b1 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -1639,6 +1639,10 @@ enum i40e_aq_phy_type {  	I40E_PHY_TYPE_1000BASE_LX		= 0x1C,  	I40E_PHY_TYPE_1000BASE_T_OPTICAL	= 0x1D,  	I40E_PHY_TYPE_20GBASE_KR2		= 0x1E, +	I40E_PHY_TYPE_25GBASE_KR		= 0x1F, +	I40E_PHY_TYPE_25GBASE_CR		= 0x20, +	I40E_PHY_TYPE_25GBASE_SR		= 0x21, +	I40E_PHY_TYPE_25GBASE_LR		= 0x22,  	I40E_PHY_TYPE_MAX  }; @@ -1647,6 +1651,7 @@ enum i40e_aq_phy_type {  #define I40E_LINK_SPEED_10GB_SHIFT	0x3  #define I40E_LINK_SPEED_40GB_SHIFT	0x4  #define I40E_LINK_SPEED_20GB_SHIFT	0x5 +#define I40E_LINK_SPEED_25GB_SHIFT	0x6  enum i40e_aq_link_speed {  	I40E_LINK_SPEED_UNKNOWN	= 0, @@ -1654,7 +1659,8 @@ enum i40e_aq_link_speed {  	I40E_LINK_SPEED_1GB	= BIT(I40E_LINK_SPEED_1000MB_SHIFT),  	I40E_LINK_SPEED_10GB	= BIT(I40E_LINK_SPEED_10GB_SHIFT),  	I40E_LINK_SPEED_40GB	= BIT(I40E_LINK_SPEED_40GB_SHIFT), -	I40E_LINK_SPEED_20GB	= BIT(I40E_LINK_SPEED_20GB_SHIFT) +	I40E_LINK_SPEED_20GB	= BIT(I40E_LINK_SPEED_20GB_SHIFT), +	I40E_LINK_SPEED_25GB	= BIT(I40E_LINK_SPEED_25GB_SHIFT),  };  struct i40e_aqc_module_desc { @@ -1677,6 +1683,8 @@ struct i40e_aq_get_phy_abilities_resp {  #define I40E_AQ_PHY_LINK_ENABLED	0x08  #define I40E_AQ_PHY_AN_ENABLED		0x10  #define I40E_AQ_PHY_FLAG_MODULE_QUAL	0x20 +#define I40E_AQ_PHY_FEC_ABILITY_KR	0x40 +#define I40E_AQ_PHY_FEC_ABILITY_RS	0x80  	__le16	eee_capability;  #define I40E_AQ_EEE_100BASE_TX		0x0002  #define I40E_AQ_EEE_1000BASE_T		0x0004 @@ -1687,7 +1695,22 @@ struct i40e_aq_get_phy_abilities_resp {  	__le32	eeer_val;  	u8	d3_lpan;  #define I40E_AQ_SET_PHY_D3_LPAN_ENA	0x01 -	u8	reserved[3]; +	u8	phy_type_ext; +#define I40E_AQ_PHY_TYPE_EXT_25G_KR	0X01 +#define I40E_AQ_PHY_TYPE_EXT_25G_CR	0X02 +#define I40E_AQ_PHY_TYPE_EXT_25G_SR	0x04 +#define I40E_AQ_PHY_TYPE_EXT_25G_LR	0x08 +	u8	fec_cfg_curr_mod_ext_info; +#define I40E_AQ_ENABLE_FEC_KR		0x01 +#define I40E_AQ_ENABLE_FEC_RS		0x02 +#define I40E_AQ_REQUEST_FEC_KR		0x04 +#define I40E_AQ_REQUEST_FEC_RS		0x08 +#define I40E_AQ_ENABLE_FEC_AUTO		0x10 +#define I40E_AQ_FEC +#define I40E_AQ_MODULE_TYPE_EXT_MASK	0xE0 +#define I40E_AQ_MODULE_TYPE_EXT_SHIFT	5 + +	u8	ext_comp_code;  	u8	phy_id[4];  	u8	module_type[3];  	u8	qualified_module_count; @@ -1709,7 +1732,20 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */  	__le16	eee_capability;  	__le32	eeer;  	u8	low_power_ctrl; -	u8	reserved[3]; +	u8	phy_type_ext; +#define I40E_AQ_PHY_TYPE_EXT_25G_KR	0X01 +#define I40E_AQ_PHY_TYPE_EXT_25G_CR	0X02 +#define I40E_AQ_PHY_TYPE_EXT_25G_SR	0x04 +#define I40E_AQ_PHY_TYPE_EXT_25G_LR	0x08 +	u8	fec_config; +#define I40E_AQ_SET_FEC_ABILITY_KR	BIT(0) +#define I40E_AQ_SET_FEC_ABILITY_RS	BIT(1) +#define I40E_AQ_SET_FEC_REQUEST_KR	BIT(2) +#define I40E_AQ_SET_FEC_REQUEST_RS	BIT(3) +#define I40E_AQ_SET_FEC_AUTO		BIT(4) +#define I40E_AQ_PHY_FEC_CONFIG_SHIFT	0x0 +#define I40E_AQ_PHY_FEC_CONFIG_MASK	(0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT) +	u8	reserved;  };  I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config); @@ -1789,9 +1825,18 @@ struct i40e_aqc_get_link_status {  #define I40E_AQ_LINK_TX_DRAINED		0x01  #define I40E_AQ_LINK_TX_FLUSHED		0x03  #define I40E_AQ_LINK_FORCED_40G		0x10 +/* 25G Error Codes */ +#define I40E_AQ_25G_NO_ERR		0X00 +#define I40E_AQ_25G_NOT_PRESENT		0X01 +#define I40E_AQ_25G_NVM_CRC_ERR		0X02 +#define I40E_AQ_25G_SBUS_UCODE_ERR	0X03 +#define I40E_AQ_25G_SERDES_UCODE_ERR	0X04 +#define I40E_AQ_25G_NIMB_UCODE_ERR	0X05  	u8	loopback; /* use defines from i40e_aqc_set_lb_mode */  	__le16	max_frame_size;  	u8	config; +#define I40E_AQ_CONFIG_FEC_KR_ENA	0x01 +#define I40E_AQ_CONFIG_FEC_RS_ENA	0x02  #define I40E_AQ_CONFIG_CRC_ENA		0x04  #define I40E_AQ_CONFIG_PACING_MASK	0x78  	u8	external_power_ability; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index 7953c13451b9..aa63b7fb993d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -53,6 +53,8 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw)  		case I40E_DEV_ID_10G_BASE_T4:  		case I40E_DEV_ID_20G_KR2:  		case I40E_DEV_ID_20G_KR2_A: +		case I40E_DEV_ID_25G_B: +		case I40E_DEV_ID_25G_SFP28:  			hw->mac.type = I40E_MAC_XL710;  			break;  		case I40E_DEV_ID_SFP_X722: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_devids.h b/drivers/net/ethernet/intel/i40evf/i40e_devids.h index 70235706915e..21dcaee1ad1d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_devids.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_devids.h @@ -39,6 +39,8 @@  #define I40E_DEV_ID_20G_KR2		0x1587  #define I40E_DEV_ID_20G_KR2_A		0x1588  #define I40E_DEV_ID_10G_BASE_T4		0x1589 +#define I40E_DEV_ID_25G_B		0x158A +#define I40E_DEV_ID_25G_SFP28		0x158B  #define I40E_DEV_ID_VF			0x154C  #define I40E_DEV_ID_VF_HV		0x1571  #define I40E_DEV_ID_SFP_X722		0x37D0 diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h index d89d52109efa..ba6c6bda0e22 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h @@ -115,6 +115,10 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,  				   u16 reg, u8 phy_addr, u16 *value);  i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,  				    u16 reg, u8 phy_addr, u16 value); +i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, u16 reg, +				   u8 phy_addr, u16 *value); +i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, u16 reg, +				    u8 phy_addr, u16 value);  u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);  i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,  				    u32 time, u32 interval); diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 75f2a2cdd738..df67ef37b7f3 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -150,7 +150,7 @@ u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw)  	return 0;  } -#define WB_STRIDE 0x3 +#define WB_STRIDE 4  /**   * i40e_clean_tx_irq - Reclaim resources after transmit completes @@ -266,7 +266,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,  		unsigned int j = i40evf_get_tx_pending(tx_ring, false);  		if (budget && -		    ((j / (WB_STRIDE + 1)) == 0) && (j > 0) && +		    ((j / WB_STRIDE) == 0) && (j > 0) &&  		    !test_bit(__I40E_DOWN, &vsi->state) &&  		    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))  			tx_ring->arm_wb = true; @@ -705,7 +705,6 @@ bool i40evf_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)  		 * because each write-back erases this info.  		 */  		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); -		rx_desc->read.hdr_addr = 0;  		rx_desc++;  		bi++; @@ -1209,7 +1208,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)  	while (likely(total_rx_packets < budget)) {  		union i40e_rx_desc *rx_desc;  		struct sk_buff *skb; -		u32 rx_status;  		u16 vlan_tag;  		u8 rx_ptype;  		u64 qword; @@ -1223,21 +1221,13 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)  		rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean); -		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); -		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> -			   I40E_RXD_QW1_PTYPE_SHIFT; -		rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >> -			    I40E_RXD_QW1_STATUS_SHIFT; - -		if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT))) -			break; -  		/* status_error_len will always be zero for unused descriptors  		 * because it's cleared in cleanup, and overlaps with hdr_addr  		 * which is always zero because packet split isn't used, if the  		 * hardware wrote DD then it will be non-zero  		 */ -		if (!rx_desc->wb.qword1.status_error_len) +		if (!i40e_test_staterr(rx_desc, +				       BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))  			break;  		/* This memory barrier is needed to keep us from reading @@ -1271,6 +1261,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)  		/* probably a little skewed due to removing CRC */  		total_rx_bytes += skb->len; +		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); +		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> +			   I40E_RXD_QW1_PTYPE_SHIFT; +  		/* populate checksum, VLAN, and protocol */  		i40evf_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype); @@ -1461,12 +1455,24 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)  	/* If work not completed, return budget and polling will return */  	if (!clean_complete) { +		const cpumask_t *aff_mask = &q_vector->affinity_mask; +		int cpu_id = smp_processor_id(); + +		/* It is possible that the interrupt affinity has changed but, +		 * if the cpu is pegged at 100%, polling will never exit while +		 * traffic continues and the interrupt will be stuck on this +		 * cpu.  We check to make sure affinity is correct before we +		 * continue to poll, otherwise we must stop polling so the +		 * interrupt can move to the correct cpu. +		 */ +		if (likely(cpumask_test_cpu(cpu_id, aff_mask))) {  tx_only: -		if (arm_wb) { -			q_vector->tx.ring[0].tx_stats.tx_force_wb++; -			i40e_enable_wb_on_itr(vsi, q_vector); +			if (arm_wb) { +				q_vector->tx.ring[0].tx_stats.tx_force_wb++; +				i40e_enable_wb_on_itr(vsi, q_vector); +			} +			return budget;  		} -		return budget;  	}  	if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR) @@ -1474,8 +1480,17 @@ tx_only:  	/* Work is done so exit the polling mode and re-enable the interrupt */  	napi_complete_done(napi, work_done); -	i40e_update_enable_itr(vsi, q_vector); -	return 0; + +	/* If we're prematurely stopping polling to fix the interrupt +	 * affinity we want to make sure polling starts back up so we +	 * issue a call to i40evf_force_wb which triggers a SW interrupt. +	 */ +	if (!clean_complete) +		i40evf_force_wb(vsi, q_vector); +	else +		i40e_update_enable_itr(vsi, q_vector); + +	return min(work_done, budget - 1);  }  /** @@ -1935,9 +1950,7 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,  	u32 td_tag = 0;  	dma_addr_t dma;  	u16 gso_segs; -	u16 desc_count = 0; -	bool tail_bump = true; -	bool do_rs = false; +	u16 desc_count = 1;  	if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {  		td_cmd |= I40E_TX_DESC_CMD_IL2TAG1; @@ -2020,8 +2033,7 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,  		tx_bi = &tx_ring->tx_bi[i];  	} -	/* set next_to_watch value indicating a packet is present */ -	first->next_to_watch = tx_desc; +	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);  	i++;  	if (i == tx_ring->count) @@ -2029,66 +2041,72 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,  	tx_ring->next_to_use = i; -	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);  	i40e_maybe_stop_tx(tx_ring, DESC_NEEDED); +	/* write last descriptor with EOP bit */ +	td_cmd |= I40E_TX_DESC_CMD_EOP; + +	/* We can OR these values together as they both are checked against +	 * 4 below and at this point desc_count will be used as a boolean value +	 * after this if/else block. +	 */ +	desc_count |= ++tx_ring->packet_stride; +  	/* Algorithm to optimize tail and RS bit setting: -	 * if xmit_more is supported -	 *	if xmit_more is true -	 *		do not update tail and do not mark RS bit. -	 *	if xmit_more is false and last xmit_more was false -	 *		if every packet spanned less than 4 desc -	 *			then set RS bit on 4th packet and update tail -	 *			on every packet -	 *		else -	 *			update tail and set RS bit on every packet. -	 *	if xmit_more is false and last_xmit_more was true -	 *		update tail and set RS bit. +	 * if queue is stopped +	 *	mark RS bit +	 *	reset packet counter +	 * else if xmit_more is supported and is true +	 *	advance packet counter to 4 +	 *	reset desc_count to 0  	 * -	 * Optimization: wmb to be issued only in case of tail update. -	 * Also optimize the Descriptor WB path for RS bit with the same -	 * algorithm. +	 * if desc_count >= 4 +	 *	mark RS bit +	 *	reset packet counter +	 * if desc_count > 0 +	 *	update tail  	 * -	 * Note: If there are less than 4 packets +	 * Note: If there are less than 4 descriptors  	 * pending and interrupts were disabled the service task will  	 * trigger a force WB.  	 */ -	if (skb->xmit_more  && -	    !netif_xmit_stopped(txring_txq(tx_ring))) { -		tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; -		tail_bump = false; -	} else if (!skb->xmit_more && -		   !netif_xmit_stopped(txring_txq(tx_ring)) && -		   (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) && -		   (tx_ring->packet_stride < WB_STRIDE) && -		   (desc_count < WB_STRIDE)) { -		tx_ring->packet_stride++; -	} else { +	if (netif_xmit_stopped(txring_txq(tx_ring))) { +		goto do_rs; +	} else if (skb->xmit_more) { +		/* set stride to arm on next packet and reset desc_count */ +		tx_ring->packet_stride = WB_STRIDE; +		desc_count = 0; +	} else if (desc_count >= WB_STRIDE) { +do_rs: +		/* write last descriptor with RS bit set */ +		td_cmd |= I40E_TX_DESC_CMD_RS;  		tx_ring->packet_stride = 0; -		tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; -		do_rs = true;  	} -	if (do_rs) -		tx_ring->packet_stride = 0;  	tx_desc->cmd_type_offset_bsz = -			build_ctob(td_cmd, td_offset, size, td_tag) | -			cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD : -						  I40E_TX_DESC_CMD_EOP) << -						  I40E_TXD_QW1_CMD_SHIFT); +			build_ctob(td_cmd, td_offset, size, td_tag); + +	/* Force memory writes to complete before letting h/w know there +	 * are new descriptors to fetch. +	 * +	 * We also use this memory barrier to make certain all of the +	 * status bits have been updated before next_to_watch is written. +	 */ +	wmb(); + +	/* set next_to_watch value indicating a packet is present */ +	first->next_to_watch = tx_desc;  	/* notify HW of packet */ -	if (!tail_bump) { -		prefetchw(tx_desc + 1); -	} else { -		/* Force memory writes to complete before letting h/w -		 * know there are new descriptors to fetch.  (Only -		 * applicable for weak-ordered memory model archs, -		 * such as IA-64). -		 */ -		wmb(); +	if (desc_count) {  		writel(i, tx_ring->tail); + +		/* we need this if more than one processor can write to our tail +		 * at a time, it synchronizes IO on IA64/Altix systems +		 */ +		mmiowb();  	} +  	return;  dma_error: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index abcdecabbc56..a5fc789f78eb 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -173,26 +173,37 @@ static inline bool i40e_test_staterr(union i40e_rx_desc *rx_desc,  #define I40E_MAX_DATA_PER_TXD_ALIGNED \  	(I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1)) -/* This ugly bit of math is equivalent to DIV_ROUNDUP(size, X) where X is - * the value I40E_MAX_DATA_PER_TXD_ALIGNED.  It is needed due to the fact - * that 12K is not a power of 2 and division is expensive.  It is used to - * approximate the number of descriptors used per linear buffer.  Note - * that this will overestimate in some cases as it doesn't account for the - * fact that we will add up to 4K - 1 in aligning the 12K buffer, however - * the error should not impact things much as large buffers usually mean - * we will use fewer descriptors then there are frags in an skb. +/** + * i40e_txd_use_count  - estimate the number of descriptors needed for Tx + * @size: transmit request size in bytes + * + * Due to hardware alignment restrictions (4K alignment), we need to + * assume that we can have no more than 12K of data per descriptor, even + * though each descriptor can take up to 16K - 1 bytes of aligned memory. + * Thus, we need to divide by 12K. But division is slow! Instead, + * we decompose the operation into shifts and one relatively cheap + * multiply operation. + * + * To divide by 12K, we first divide by 4K, then divide by 3: + *     To divide by 4K, shift right by 12 bits + *     To divide by 3, multiply by 85, then divide by 256 + *     (Divide by 256 is done by shifting right by 8 bits) + * Finally, we add one to round up. Because 256 isn't an exact multiple of + * 3, we'll underestimate near each multiple of 12K. This is actually more + * accurate as we have 4K - 1 of wiggle room that we can fit into the last + * segment.  For our purposes this is accurate out to 1M which is orders of + * magnitude greater than our largest possible GSO size. + * + * This would then be implemented as: + *     return (((size >> 12) * 85) >> 8) + 1; + * + * Since multiplication and division are commutative, we can reorder + * operations into: + *     return ((size * 85) >> 20) + 1;   */  static inline unsigned int i40e_txd_use_count(unsigned int size)  { -	const unsigned int max = I40E_MAX_DATA_PER_TXD_ALIGNED; -	const unsigned int reciprocal = ((1ull << 32) - 1 + (max / 2)) / max; -	unsigned int adjust = ~(u32)0; - -	/* if we rounded up on the reciprocal pull down the adjustment */ -	if ((max * reciprocal) > adjust) -		adjust = ~(u32)(reciprocal - 1); - -	return (u32)((((u64)size * reciprocal) + adjust) >> 32); +	return ((size * 85) >> 20) + 1;  }  /* Tx Descriptors needed, worst case */ @@ -309,7 +320,6 @@ struct i40e_ring {  	bool ring_active;		/* is ring online or not */  	bool arm_wb;		/* do something to arm write back */  	u8 packet_stride; -#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)  	u16 flags;  #define I40E_TXR_FLAGS_WB_ON_ITR	BIT(0) diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 97f96e0d9c4c..c85e8a31c072 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -187,47 +187,59 @@ struct i40e_link_status {  #define I40E_MODULE_TYPE_1000BASE_T	0x08  }; -enum i40e_aq_capabilities_phy_type { -	I40E_CAP_PHY_TYPE_SGMII		  = BIT(I40E_PHY_TYPE_SGMII), -	I40E_CAP_PHY_TYPE_1000BASE_KX	  = BIT(I40E_PHY_TYPE_1000BASE_KX), -	I40E_CAP_PHY_TYPE_10GBASE_KX4	  = BIT(I40E_PHY_TYPE_10GBASE_KX4), -	I40E_CAP_PHY_TYPE_10GBASE_KR	  = BIT(I40E_PHY_TYPE_10GBASE_KR), -	I40E_CAP_PHY_TYPE_40GBASE_KR4	  = BIT(I40E_PHY_TYPE_40GBASE_KR4), -	I40E_CAP_PHY_TYPE_XAUI		  = BIT(I40E_PHY_TYPE_XAUI), -	I40E_CAP_PHY_TYPE_XFI		  = BIT(I40E_PHY_TYPE_XFI), -	I40E_CAP_PHY_TYPE_SFI		  = BIT(I40E_PHY_TYPE_SFI), -	I40E_CAP_PHY_TYPE_XLAUI		  = BIT(I40E_PHY_TYPE_XLAUI), -	I40E_CAP_PHY_TYPE_XLPPI		  = BIT(I40E_PHY_TYPE_XLPPI), -	I40E_CAP_PHY_TYPE_40GBASE_CR4_CU  = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU), -	I40E_CAP_PHY_TYPE_10GBASE_CR1_CU  = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU), -	I40E_CAP_PHY_TYPE_10GBASE_AOC	  = BIT(I40E_PHY_TYPE_10GBASE_AOC), -	I40E_CAP_PHY_TYPE_40GBASE_AOC	  = BIT(I40E_PHY_TYPE_40GBASE_AOC), -	I40E_CAP_PHY_TYPE_100BASE_TX	  = BIT(I40E_PHY_TYPE_100BASE_TX), -	I40E_CAP_PHY_TYPE_1000BASE_T	  = BIT(I40E_PHY_TYPE_1000BASE_T), -	I40E_CAP_PHY_TYPE_10GBASE_T	  = BIT(I40E_PHY_TYPE_10GBASE_T), -	I40E_CAP_PHY_TYPE_10GBASE_SR	  = BIT(I40E_PHY_TYPE_10GBASE_SR), -	I40E_CAP_PHY_TYPE_10GBASE_LR	  = BIT(I40E_PHY_TYPE_10GBASE_LR), -	I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU), -	I40E_CAP_PHY_TYPE_10GBASE_CR1	  = BIT(I40E_PHY_TYPE_10GBASE_CR1), -	I40E_CAP_PHY_TYPE_40GBASE_CR4	  = BIT(I40E_PHY_TYPE_40GBASE_CR4), -	I40E_CAP_PHY_TYPE_40GBASE_SR4	  = BIT(I40E_PHY_TYPE_40GBASE_SR4), -	I40E_CAP_PHY_TYPE_40GBASE_LR4	  = BIT(I40E_PHY_TYPE_40GBASE_LR4), -	I40E_CAP_PHY_TYPE_1000BASE_SX	  = BIT(I40E_PHY_TYPE_1000BASE_SX), -	I40E_CAP_PHY_TYPE_1000BASE_LX	  = BIT(I40E_PHY_TYPE_1000BASE_LX), -	I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL = -					 BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL), -	I40E_CAP_PHY_TYPE_20GBASE_KR2	  = BIT(I40E_PHY_TYPE_20GBASE_KR2) -}; -  struct i40e_phy_info {  	struct i40e_link_status link_info;  	struct i40e_link_status link_info_old;  	bool get_link_info;  	enum i40e_media_type media_type;  	/* all the phy types the NVM is capable of */ -	enum i40e_aq_capabilities_phy_type phy_types; -}; - +	u64 phy_types; +}; + +#define I40E_CAP_PHY_TYPE_SGMII BIT_ULL(I40E_PHY_TYPE_SGMII) +#define I40E_CAP_PHY_TYPE_1000BASE_KX BIT_ULL(I40E_PHY_TYPE_1000BASE_KX) +#define I40E_CAP_PHY_TYPE_10GBASE_KX4 BIT_ULL(I40E_PHY_TYPE_10GBASE_KX4) +#define I40E_CAP_PHY_TYPE_10GBASE_KR BIT_ULL(I40E_PHY_TYPE_10GBASE_KR) +#define I40E_CAP_PHY_TYPE_40GBASE_KR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_KR4) +#define I40E_CAP_PHY_TYPE_XAUI BIT_ULL(I40E_PHY_TYPE_XAUI) +#define I40E_CAP_PHY_TYPE_XFI BIT_ULL(I40E_PHY_TYPE_XFI) +#define I40E_CAP_PHY_TYPE_SFI BIT_ULL(I40E_PHY_TYPE_SFI) +#define I40E_CAP_PHY_TYPE_XLAUI BIT_ULL(I40E_PHY_TYPE_XLAUI) +#define I40E_CAP_PHY_TYPE_XLPPI BIT_ULL(I40E_PHY_TYPE_XLPPI) +#define I40E_CAP_PHY_TYPE_40GBASE_CR4_CU BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4_CU) +#define I40E_CAP_PHY_TYPE_10GBASE_CR1_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1_CU) +#define I40E_CAP_PHY_TYPE_10GBASE_AOC BIT_ULL(I40E_PHY_TYPE_10GBASE_AOC) +#define I40E_CAP_PHY_TYPE_40GBASE_AOC BIT_ULL(I40E_PHY_TYPE_40GBASE_AOC) +#define I40E_CAP_PHY_TYPE_100BASE_TX BIT_ULL(I40E_PHY_TYPE_100BASE_TX) +#define I40E_CAP_PHY_TYPE_1000BASE_T BIT_ULL(I40E_PHY_TYPE_1000BASE_T) +#define I40E_CAP_PHY_TYPE_10GBASE_T BIT_ULL(I40E_PHY_TYPE_10GBASE_T) +#define I40E_CAP_PHY_TYPE_10GBASE_SR BIT_ULL(I40E_PHY_TYPE_10GBASE_SR) +#define I40E_CAP_PHY_TYPE_10GBASE_LR BIT_ULL(I40E_PHY_TYPE_10GBASE_LR) +#define I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_SFPP_CU) +#define I40E_CAP_PHY_TYPE_10GBASE_CR1 BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1) +#define I40E_CAP_PHY_TYPE_40GBASE_CR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4) +#define I40E_CAP_PHY_TYPE_40GBASE_SR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_SR4) +#define I40E_CAP_PHY_TYPE_40GBASE_LR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_LR4) +#define I40E_CAP_PHY_TYPE_1000BASE_SX BIT_ULL(I40E_PHY_TYPE_1000BASE_SX) +#define I40E_CAP_PHY_TYPE_1000BASE_LX BIT_ULL(I40E_PHY_TYPE_1000BASE_LX) +#define I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL \ +				BIT_ULL(I40E_PHY_TYPE_1000BASE_T_OPTICAL) +#define I40E_CAP_PHY_TYPE_20GBASE_KR2 BIT_ULL(I40E_PHY_TYPE_20GBASE_KR2) +/* Defining the macro I40E_TYPE_OFFSET to implement a bit shift for some + * PHY types. There is an unused bit (31) in the I40E_CAP_PHY_TYPE_* bit + * fields but no corresponding gap in the i40e_aq_phy_type enumeration. So, + * a shift is needed to adjust for this with values larger than 31. The + * only affected values are I40E_PHY_TYPE_25GBASE_*. + */ +#define I40E_PHY_TYPE_OFFSET 1 +#define I40E_CAP_PHY_TYPE_25GBASE_KR BIT_ULL(I40E_PHY_TYPE_25GBASE_KR + \ +					     I40E_PHY_TYPE_OFFSET) +#define I40E_CAP_PHY_TYPE_25GBASE_CR BIT_ULL(I40E_PHY_TYPE_25GBASE_CR + \ +					     I40E_PHY_TYPE_OFFSET) +#define I40E_CAP_PHY_TYPE_25GBASE_SR BIT_ULL(I40E_PHY_TYPE_25GBASE_SR + \ +					     I40E_PHY_TYPE_OFFSET) +#define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \ +					     I40E_PHY_TYPE_OFFSET)  #define I40E_HW_CAP_MAX_GPIO			30  /* Capabilities of a PF or a VF or the whole device */  struct i40e_hw_capabilities { @@ -237,6 +249,10 @@ struct i40e_hw_capabilities {  #define I40E_NVM_IMAGE_TYPE_UDP_CLOUD	0x3  	u32  management_mode; +	u32  mng_protocols_over_mctp; +#define I40E_MNG_PROTOCOL_PLDM		0x2 +#define I40E_MNG_PROTOCOL_OEM_COMMANDS	0x4 +#define I40E_MNG_PROTOCOL_NCSI		0x8  	u32  npar_enable;  	u32  os2bmc;  	u32  valid_functions; @@ -348,6 +364,7 @@ enum i40e_nvmupd_state {  	I40E_NVMUPD_STATE_WRITING,  	I40E_NVMUPD_STATE_INIT_WAIT,  	I40E_NVMUPD_STATE_WRITE_WAIT, +	I40E_NVMUPD_STATE_ERROR  };  /* nvm_access definition and its masks/shifts need to be accessible to diff --git a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h index bd691ad86673..fc374f833aa9 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h @@ -162,6 +162,10 @@ struct i40e_virtchnl_vsi_resource {  #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF		0X00080000  #define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM	0X00100000 +#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \ +				    I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \ +				    I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) +  struct i40e_virtchnl_vf_resource {  	u16 num_vsis;  	u16 num_queue_pairs; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index c5fd724313c7..fffe4cf2c20b 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -107,7 +107,8 @@ struct i40e_q_vector {  	int v_idx;	/* vector index in list */  	char name[IFNAMSIZ + 9];  	bool arm_wb_state; -	cpumask_var_t affinity_mask; +	cpumask_t affinity_mask; +	struct irq_affinity_notify affinity_notify;  };  /* Helper macros to switch between ints/sec and what the register uses. diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c index a9940154eead..272d600c1ed0 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c @@ -85,6 +85,14 @@ static int i40evf_get_settings(struct net_device *netdev,  	case I40E_LINK_SPEED_40GB:  		ethtool_cmd_speed_set(ecmd, SPEED_40000);  		break; +	case I40E_LINK_SPEED_25GB: +#ifdef SPEED_25000 +		ethtool_cmd_speed_set(ecmd, SPEED_25000); +#else +		netdev_info(netdev, +			    "Speed is 25G, display not supported by this version of ethtool.\n"); +#endif +		break;  	case I40E_LINK_SPEED_20GB:  		ethtool_cmd_speed_set(ecmd, SPEED_20000);  		break; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 14372810fc27..c0fc53361800 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -38,7 +38,7 @@ static const char i40evf_driver_string[] =  #define DRV_VERSION_MAJOR 1  #define DRV_VERSION_MINOR 6 -#define DRV_VERSION_BUILD 16 +#define DRV_VERSION_BUILD 25  #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \  	     __stringify(DRV_VERSION_MINOR) "." \  	     __stringify(DRV_VERSION_BUILD) \ @@ -207,6 +207,9 @@ static void i40evf_misc_irq_disable(struct i40evf_adapter *adapter)  {  	struct i40e_hw *hw = &adapter->hw; +	if (!adapter->msix_entries) +		return; +  	wr32(hw, I40E_VFINT_DYN_CTL01, 0);  	/* read flush */ @@ -496,6 +499,33 @@ static void i40evf_netpoll(struct net_device *netdev)  #endif  /** + * i40evf_irq_affinity_notify - Callback for affinity changes + * @notify: context as to what irq was changed + * @mask: the new affinity mask + * + * This is a callback function used by the irq_set_affinity_notifier function + * so that we may register to receive changes to the irq affinity masks. + **/ +static void i40evf_irq_affinity_notify(struct irq_affinity_notify *notify, +				       const cpumask_t *mask) +{ +	struct i40e_q_vector *q_vector = +		container_of(notify, struct i40e_q_vector, affinity_notify); + +	q_vector->affinity_mask = *mask; +} + +/** + * i40evf_irq_affinity_release - Callback for affinity notifier release + * @ref: internal core kernel usage + * + * This is a callback function used by the irq_set_affinity_notifier function + * to inform the current notification subscriber that they will no longer + * receive notifications. + **/ +static void i40evf_irq_affinity_release(struct kref *ref) {} + +/**   * i40evf_request_traffic_irqs - Initialize MSI-X interrupts   * @adapter: board private structure   * @@ -507,6 +537,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)  {  	int vector, err, q_vectors;  	int rx_int_idx = 0, tx_int_idx = 0; +	int irq_num;  	i40evf_irq_disable(adapter);  	/* Decrement for Other and TCP Timer vectors */ @@ -514,6 +545,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)  	for (vector = 0; vector < q_vectors; vector++) {  		struct i40e_q_vector *q_vector = &adapter->q_vectors[vector]; +		irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;  		if (q_vector->tx.ring && q_vector->rx.ring) {  			snprintf(q_vector->name, sizeof(q_vector->name) - 1, @@ -532,21 +564,23 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)  			/* skip this unused q_vector */  			continue;  		} -		err = request_irq( -			adapter->msix_entries[vector + NONQ_VECS].vector, -			i40evf_msix_clean_rings, -			0, -			q_vector->name, -			q_vector); +		err = request_irq(irq_num, +				  i40evf_msix_clean_rings, +				  0, +				  q_vector->name, +				  q_vector);  		if (err) {  			dev_info(&adapter->pdev->dev,  				 "Request_irq failed, error: %d\n", err);  			goto free_queue_irqs;  		} +		/* register for affinity change notifications */ +		q_vector->affinity_notify.notify = i40evf_irq_affinity_notify; +		q_vector->affinity_notify.release = +						   i40evf_irq_affinity_release; +		irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);  		/* assign the mask for this irq */ -		irq_set_affinity_hint( -			adapter->msix_entries[vector + NONQ_VECS].vector, -			q_vector->affinity_mask); +		irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);  	}  	return 0; @@ -554,11 +588,10 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)  free_queue_irqs:  	while (vector) {  		vector--; -		irq_set_affinity_hint( -			adapter->msix_entries[vector + NONQ_VECS].vector, -			NULL); -		free_irq(adapter->msix_entries[vector + NONQ_VECS].vector, -			 &adapter->q_vectors[vector]); +		irq_num = adapter->msix_entries[vector + NONQ_VECS].vector; +		irq_set_affinity_notifier(irq_num, NULL); +		irq_set_affinity_hint(irq_num, NULL); +		free_irq(irq_num, &adapter->q_vectors[vector]);  	}  	return err;  } @@ -599,16 +632,18 @@ static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)   **/  static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter)  { -	int i; -	int q_vectors; +	int vector, irq_num, q_vectors; + +	if (!adapter->msix_entries) +		return;  	q_vectors = adapter->num_msix_vectors - NONQ_VECS; -	for (i = 0; i < q_vectors; i++) { -		irq_set_affinity_hint(adapter->msix_entries[i+1].vector, -				      NULL); -		free_irq(adapter->msix_entries[i+1].vector, -			 &adapter->q_vectors[i]); +	for (vector = 0; vector < q_vectors; vector++) { +		irq_num = adapter->msix_entries[vector + NONQ_VECS].vector; +		irq_set_affinity_notifier(irq_num, NULL); +		irq_set_affinity_hint(irq_num, NULL); +		free_irq(irq_num, &adapter->q_vectors[vector]);  	}  } @@ -622,6 +657,9 @@ static void i40evf_free_misc_irq(struct i40evf_adapter *adapter)  {  	struct net_device *netdev = adapter->netdev; +	if (!adapter->msix_entries) +		return; +  	free_irq(adapter->msix_entries[0].vector, netdev);  } @@ -1396,6 +1434,9 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)  	int q_idx, num_q_vectors;  	int napi_vectors; +	if (!adapter->q_vectors) +		return; +  	num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;  	napi_vectors = adapter->num_active_queues; @@ -1405,6 +1446,7 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)  			netif_napi_del(&q_vector->napi);  	}  	kfree(adapter->q_vectors); +	adapter->q_vectors = NULL;  }  /** @@ -1414,6 +1456,9 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)   **/  void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter)  { +	if (!adapter->msix_entries) +		return; +  	pci_disable_msix(adapter->pdev);  	kfree(adapter->msix_entries);  	adapter->msix_entries = NULL; @@ -1664,6 +1709,49 @@ restart_watchdog:  	schedule_work(&adapter->adminq_task);  } +static void i40evf_disable_vf(struct i40evf_adapter *adapter) +{ +	struct i40evf_mac_filter *f, *ftmp; +	struct i40evf_vlan_filter *fv, *fvtmp; + +	adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED; + +	if (netif_running(adapter->netdev)) { +		set_bit(__I40E_DOWN, &adapter->vsi.state); +		netif_carrier_off(adapter->netdev); +		netif_tx_disable(adapter->netdev); +		adapter->link_up = false; +		i40evf_napi_disable_all(adapter); +		i40evf_irq_disable(adapter); +		i40evf_free_traffic_irqs(adapter); +		i40evf_free_all_tx_resources(adapter); +		i40evf_free_all_rx_resources(adapter); +	} + +	/* Delete all of the filters, both MAC and VLAN. */ +	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) { +		list_del(&f->list); +		kfree(f); +	} + +	list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list, list) { +		list_del(&fv->list); +		kfree(fv); +	} + +	i40evf_free_misc_irq(adapter); +	i40evf_reset_interrupt_capability(adapter); +	i40evf_free_queues(adapter); +	i40evf_free_q_vectors(adapter); +	kfree(adapter->vf_res); +	i40evf_shutdown_adminq(&adapter->hw); +	adapter->netdev->flags &= ~IFF_UP; +	clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); +	adapter->flags &= ~I40EVF_FLAG_RESET_PENDING; +	adapter->state = __I40EVF_DOWN; +	dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n"); +} +  #define I40EVF_RESET_WAIT_MS 10  #define I40EVF_RESET_WAIT_COUNT 500  /** @@ -1717,60 +1805,21 @@ static void i40evf_reset_task(struct work_struct *work)  	/* wait until the reset is complete and the PF is responding to us */  	for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) { +		/* sleep first to make sure a minimum wait time is met */ +		msleep(I40EVF_RESET_WAIT_MS); +  		reg_val = rd32(hw, I40E_VFGEN_RSTAT) &  			  I40E_VFGEN_RSTAT_VFR_STATE_MASK;  		if (reg_val == I40E_VFR_VFACTIVE)  			break; -		msleep(I40EVF_RESET_WAIT_MS);  	} +  	pci_set_master(adapter->pdev); -	/* extra wait to make sure minimum wait is met */ -	msleep(I40EVF_RESET_WAIT_MS); -	if (i == I40EVF_RESET_WAIT_COUNT) { -		struct i40evf_mac_filter *ftmp; -		struct i40evf_vlan_filter *fv, *fvtmp; -		/* reset never finished */ +	if (i == I40EVF_RESET_WAIT_COUNT) {  		dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",  			reg_val); -		adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED; - -		if (netif_running(adapter->netdev)) { -			set_bit(__I40E_DOWN, &adapter->vsi.state); -			netif_carrier_off(netdev); -			netif_tx_disable(netdev); -			adapter->link_up = false; -			i40evf_napi_disable_all(adapter); -			i40evf_irq_disable(adapter); -			i40evf_free_traffic_irqs(adapter); -			i40evf_free_all_tx_resources(adapter); -			i40evf_free_all_rx_resources(adapter); -		} - -		/* Delete all of the filters, both MAC and VLAN. */ -		list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, -					 list) { -			list_del(&f->list); -			kfree(f); -		} - -		list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list, -					 list) { -			list_del(&fv->list); -			kfree(fv); -		} - -		i40evf_free_misc_irq(adapter); -		i40evf_reset_interrupt_capability(adapter); -		i40evf_free_queues(adapter); -		i40evf_free_q_vectors(adapter); -		kfree(adapter->vf_res); -		i40evf_shutdown_adminq(hw); -		adapter->netdev->flags &= ~IFF_UP; -		clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); -		adapter->flags &= ~I40EVF_FLAG_RESET_PENDING; -		adapter->state = __I40EVF_DOWN; -		dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n"); +		i40evf_disable_vf(adapter);  		return; /* Do not attempt to reinit. It's dead, Jim. */  	} @@ -2133,10 +2182,6 @@ static struct net_device_stats *i40evf_get_stats(struct net_device *netdev)  static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)  {  	struct i40evf_adapter *adapter = netdev_priv(netdev); -	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - -	if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER)) -		return -EINVAL;  	netdev->mtu = new_mtu;  	adapter->flags |= I40EVF_FLAG_RESET_NEEDED; @@ -2145,6 +2190,64 @@ static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)  	return 0;  } +/** + * i40evf_features_check - Validate encapsulated packet conforms to limits + * @skb: skb buff + * @netdev: This physical port's netdev + * @features: Offload features that the stack believes apply + **/ +static netdev_features_t i40evf_features_check(struct sk_buff *skb, +					       struct net_device *dev, +					       netdev_features_t features) +{ +	size_t len; + +	/* No point in doing any of this if neither checksum nor GSO are +	 * being requested for this frame.  We can rule out both by just +	 * checking for CHECKSUM_PARTIAL +	 */ +	if (skb->ip_summed != CHECKSUM_PARTIAL) +		return features; + +	/* We cannot support GSO if the MSS is going to be less than +	 * 64 bytes.  If it is then we need to drop support for GSO. +	 */ +	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64)) +		features &= ~NETIF_F_GSO_MASK; + +	/* MACLEN can support at most 63 words */ +	len = skb_network_header(skb) - skb->data; +	if (len & ~(63 * 2)) +		goto out_err; + +	/* IPLEN and EIPLEN can support at most 127 dwords */ +	len = skb_transport_header(skb) - skb_network_header(skb); +	if (len & ~(127 * 4)) +		goto out_err; + +	if (skb->encapsulation) { +		/* L4TUNLEN can support 127 words */ +		len = skb_inner_network_header(skb) - skb_transport_header(skb); +		if (len & ~(127 * 2)) +			goto out_err; + +		/* IPLEN can support at most 127 dwords */ +		len = skb_inner_transport_header(skb) - +		      skb_inner_network_header(skb); +		if (len & ~(127 * 4)) +			goto out_err; +	} + +	/* No need to validate L4LEN as TCP is the only protocol with a +	 * a flexible value and we support all possible values supported +	 * by TCP, which is at most 15 dwords +	 */ + +	return features; +out_err: +	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); +} +  #define I40EVF_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_TX |\  			      NETIF_F_HW_VLAN_CTAG_RX |\  			      NETIF_F_HW_VLAN_CTAG_FILTER) @@ -2179,6 +2282,7 @@ static const struct net_device_ops i40evf_netdev_ops = {  	.ndo_tx_timeout		= i40evf_tx_timeout,  	.ndo_vlan_rx_add_vid	= i40evf_vlan_rx_add_vid,  	.ndo_vlan_rx_kill_vid	= i40evf_vlan_rx_kill_vid, +	.ndo_features_check	= i40evf_features_check,  	.ndo_fix_features	= i40evf_fix_features,  #ifdef CONFIG_NET_POLL_CONTROLLER  	.ndo_poll_controller	= i40evf_netpoll, @@ -2424,6 +2528,10 @@ static void i40evf_init_task(struct work_struct *work)  	i40evf_set_ethtool_ops(netdev);  	netdev->watchdog_timeo = 5 * HZ; +	/* MTU range: 68 - 9710 */ +	netdev->min_mtu = ETH_MIN_MTU; +	netdev->max_mtu = I40E_MAX_RXBUFFER - (ETH_HLEN + ETH_FCS_LEN); +  	if (!is_valid_ether_addr(adapter->hw.mac.addr)) {  		dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n",  			 adapter->hw.mac.addr); @@ -2764,12 +2872,10 @@ static void i40evf_remove(struct pci_dev *pdev)  		msleep(50);  	} -	if (adapter->msix_entries) { -		i40evf_misc_irq_disable(adapter); -		i40evf_free_misc_irq(adapter); -		i40evf_reset_interrupt_capability(adapter); -		i40evf_free_q_vectors(adapter); -	} +	i40evf_misc_irq_disable(adapter); +	i40evf_free_misc_irq(adapter); +	i40evf_reset_interrupt_capability(adapter); +	i40evf_free_q_vectors(adapter);  	if (adapter->watchdog_timer.function)  		del_timer_sync(&adapter->watchdog_timer); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index ddf478d6322b..2059a8e88908 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -836,6 +836,9 @@ static void i40evf_print_link_message(struct i40evf_adapter *adapter)  	case I40E_LINK_SPEED_40GB:  		speed = "40 G";  		break; +	case I40E_LINK_SPEED_25GB: +		speed = "25 G"; +		break;  	case I40E_LINK_SPEED_20GB:  		speed = "20 G";  		break; diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index 2688180a7acd..8aee314332a8 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h @@ -357,7 +357,8 @@  #define ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.3ac packet */  /* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */ -#define MAX_JUMBO_FRAME_SIZE	0x2600 +#define MAX_JUMBO_FRAME_SIZE		0x2600 +#define MAX_STD_JUMBO_FRAME_SIZE	9216  /* PBA constants */  #define E1000_PBA_34K 0x0022 diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index edc9a6ac5169..cae24a8ccf47 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2468,6 +2468,10 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	netdev->priv_flags |= IFF_UNICAST_FLT; +	/* MTU range: 68 - 9216 */ +	netdev->min_mtu = ETH_MIN_MTU; +	netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; +  	adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);  	/* before reading the NVM, reset the controller to put the device in a @@ -4931,11 +4935,15 @@ static int igb_tso(struct igb_ring *tx_ring,  	/* initialize outer IP header fields */  	if (ip.v4->version == 4) { +		unsigned char *csum_start = skb_checksum_start(skb); +		unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); +  		/* IP header will have to cancel out any data that  		 * is not a part of the outer IP header  		 */ -		ip.v4->check = csum_fold(csum_add(lco_csum(skb), -						  csum_unfold(l4.tcp->check))); +		ip.v4->check = csum_fold(csum_partial(trans_start, +						      csum_start - trans_start, +						      0));  		type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;  		ip.v4->tot_len = 0; @@ -5408,17 +5416,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)  	struct pci_dev *pdev = adapter->pdev;  	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; -	if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { -		dev_err(&pdev->dev, "Invalid MTU setting\n"); -		return -EINVAL; -	} - -#define MAX_STD_JUMBO_FRAME_SIZE 9238 -	if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { -		dev_err(&pdev->dev, "MTU > 9216 not supported.\n"); -		return -EINVAL; -	} -  	/* adjust max frame to be at least the size of a standard frame */  	if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))  		max_frame = ETH_FRAME_LEN + ETH_FCS_LEN; diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index a7895c4cbcc3..c30eea8399a7 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -226,7 +226,7 @@ static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb)  	return 0;  } -static int igb_ptp_adjfreq_82580(struct ptp_clock_info *ptp, s32 ppb) +static int igb_ptp_adjfine_82580(struct ptp_clock_info *ptp, long scaled_ppm)  {  	struct igb_adapter *igb = container_of(ptp, struct igb_adapter,  					       ptp_caps); @@ -235,13 +235,13 @@ static int igb_ptp_adjfreq_82580(struct ptp_clock_info *ptp, s32 ppb)  	u64 rate;  	u32 inca; -	if (ppb < 0) { +	if (scaled_ppm < 0) {  		neg_adj = 1; -		ppb = -ppb; +		scaled_ppm = -scaled_ppm;  	} -	rate = ppb; -	rate <<= 26; -	rate = div_u64(rate, 1953125); +	rate = scaled_ppm; +	rate <<= 13; +	rate = div_u64(rate, 15625);  	inca = rate & INCVALUE_MASK;  	if (neg_adj) @@ -1103,7 +1103,7 @@ void igb_ptp_init(struct igb_adapter *adapter)  		adapter->ptp_caps.max_adj = 62499999;  		adapter->ptp_caps.n_ext_ts = 0;  		adapter->ptp_caps.pps = 0; -		adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; +		adapter->ptp_caps.adjfine = igb_ptp_adjfine_82580;  		adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576;  		adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576;  		adapter->ptp_caps.settime64 = igb_ptp_settime_82576; @@ -1131,7 +1131,7 @@ void igb_ptp_init(struct igb_adapter *adapter)  		adapter->ptp_caps.n_pins = IGB_N_SDP;  		adapter->ptp_caps.pps = 1;  		adapter->ptp_caps.pin_config = adapter->sdp_config; -		adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; +		adapter->ptp_caps.adjfine = igb_ptp_adjfine_82580;  		adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210;  		adapter->ptp_caps.gettime64 = igb_ptp_gettime_i210;  		adapter->ptp_caps.settime64 = igb_ptp_settime_i210; diff --git a/drivers/net/ethernet/intel/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h index ee1ef08d7fc4..f1789d192e24 100644 --- a/drivers/net/ethernet/intel/igbvf/defines.h +++ b/drivers/net/ethernet/intel/igbvf/defines.h @@ -85,7 +85,8 @@  #define E1000_TXD_CMD_DEXT	0x20000000 /* Desc extension (0 = legacy) */  #define E1000_TXD_STAT_DD	0x00000001 /* Desc Done */ -#define MAX_JUMBO_FRAME_SIZE	0x3F00 +#define MAX_JUMBO_FRAME_SIZE		0x3F00 +#define MAX_STD_JUMBO_FRAME_SIZE	9216  /* 802.1q VLAN Packet Size */  #define VLAN_TAG_SIZE		4    /* 802.3ac tag (not DMA'd) */ diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 12bb877df860..839ba110f7fb 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -1965,11 +1965,15 @@ static int igbvf_tso(struct igbvf_ring *tx_ring,  	/* initialize outer IP header fields */  	if (ip.v4->version == 4) { +		unsigned char *csum_start = skb_checksum_start(skb); +		unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); +  		/* IP header will have to cancel out any data that  		 * is not a part of the outer IP header  		 */ -		ip.v4->check = csum_fold(csum_add(lco_csum(skb), -						  csum_unfold(l4.tcp->check))); +		ip.v4->check = csum_fold(csum_partial(trans_start, +						      csum_start - trans_start, +						      0));  		type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;  		ip.v4->tot_len = 0; @@ -2356,16 +2360,6 @@ static int igbvf_change_mtu(struct net_device *netdev, int new_mtu)  	struct igbvf_adapter *adapter = netdev_priv(netdev);  	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; -	if (new_mtu < 68 || new_mtu > INT_MAX - ETH_HLEN - ETH_FCS_LEN || -	    max_frame > MAX_JUMBO_FRAME_SIZE) -		return -EINVAL; - -#define MAX_STD_JUMBO_FRAME_SIZE 9234 -	if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { -		dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n"); -		return -EINVAL; -	} -  	while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))  		usleep_range(1000, 2000);  	/* igbvf_down has a dependency on max_frame_size */ @@ -2786,6 +2780,10 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  			    NETIF_F_HW_VLAN_CTAG_RX |  			    NETIF_F_HW_VLAN_CTAG_TX; +	/* MTU range: 68 - 9216 */ +	netdev->min_mtu = ETH_MIN_MTU; +	netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; +  	/*reset the controller to put the device in a known good state */  	err = hw->mac.ops.reset_hw(hw);  	if (err) { diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index 31f91459312f..5826b1ddedcf 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -487,6 +487,10 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  		netdev->vlan_features |= NETIF_F_HIGHDMA;  	} +	/* MTU range: 68 - 16114 */ +	netdev->min_mtu = ETH_MIN_MTU; +	netdev->max_mtu = IXGB_MAX_JUMBO_FRAME_SIZE - ETH_HLEN; +  	/* make sure the EEPROM is good */  	if (!ixgb_validate_eeprom_checksum(&adapter->hw)) { @@ -1619,18 +1623,6 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)  {  	struct ixgb_adapter *adapter = netdev_priv(netdev);  	int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH; -	int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH; - -	/* MTU < 68 is an error for IPv4 traffic, just don't allow it */ -	if ((new_mtu < 68) || -	    (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) { -		netif_err(adapter, probe, adapter->netdev, -			  "Invalid MTU setting %d\n", new_mtu); -		return -EINVAL; -	} - -	if (old_max_frame == max_frame) -		return 0;  	if (netif_running(netdev))  		ixgb_down(adapter, true); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index b06e32d0d22a..ef81c3d8c295 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -1027,4 +1027,6 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,  				  struct ixgbe_ring *tx_ring);  u32 ixgbe_rss_indir_tbl_entries(struct ixgbe_adapter *adapter);  void ixgbe_store_reta(struct ixgbe_adapter *adapter); +s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, +		       u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);  #endif /* _IXGBE_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index fb51be74dd4c..805ab319e578 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -367,7 +367,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)  	}  	/* Negotiate the fc mode to use */ -	ixgbe_fc_autoneg(hw); +	hw->mac.ops.fc_autoneg(hw);  	/* Disable any previous flow control settings */  	fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); @@ -1179,6 +1179,7 @@ static const struct ixgbe_mac_operations mac_ops_82598 = {  	.get_link_capabilities	= &ixgbe_get_link_capabilities_82598,  	.led_on			= &ixgbe_led_on_generic,  	.led_off		= &ixgbe_led_off_generic, +	.init_led_link_act	= ixgbe_init_led_link_act_generic,  	.blink_led_start	= &ixgbe_blink_led_start_generic,  	.blink_led_stop		= &ixgbe_blink_led_stop_generic,  	.set_rar		= &ixgbe_set_rar_generic, @@ -1193,6 +1194,7 @@ static const struct ixgbe_mac_operations mac_ops_82598 = {  	.set_vfta		= &ixgbe_set_vfta_82598,  	.fc_enable		= &ixgbe_fc_enable_82598,  	.setup_fc		= ixgbe_setup_fc_generic, +	.fc_autoneg		= ixgbe_fc_autoneg,  	.set_fw_drv_ver         = NULL,  	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,  	.release_swfw_sync      = &ixgbe_release_swfw_sync, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 63b25006ac90..e00aaeb91827 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -2204,6 +2204,7 @@ static const struct ixgbe_mac_operations mac_ops_82599 = {  	.get_link_capabilities  = &ixgbe_get_link_capabilities_82599,  	.led_on                 = &ixgbe_led_on_generic,  	.led_off                = &ixgbe_led_off_generic, +	.init_led_link_act	= ixgbe_init_led_link_act_generic,  	.blink_led_start        = &ixgbe_blink_led_start_generic,  	.blink_led_stop         = &ixgbe_blink_led_stop_generic,  	.set_rar                = &ixgbe_set_rar_generic, @@ -2219,6 +2220,7 @@ static const struct ixgbe_mac_operations mac_ops_82599 = {  	.set_vfta               = &ixgbe_set_vfta_generic,  	.fc_enable              = &ixgbe_fc_enable_generic,  	.setup_fc		= ixgbe_setup_fc_generic, +	.fc_autoneg		= ixgbe_fc_autoneg,  	.set_fw_drv_ver         = &ixgbe_set_fw_drv_ver_generic,  	.init_uta_tables        = &ixgbe_init_uta_tables_generic,  	.setup_sfp              = &ixgbe_setup_sfp_modules_82599, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 77d3039283f6..8832df3eba25 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -298,10 +298,12 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)  	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);  	IXGBE_WRITE_FLUSH(hw); -	/* Setup flow control */ -	ret_val = hw->mac.ops.setup_fc(hw); -	if (ret_val) -		return ret_val; +	/* Setup flow control if method for doing so */ +	if (hw->mac.ops.setup_fc) { +		ret_val = hw->mac.ops.setup_fc(hw); +		if (ret_val) +			return ret_val; +	}  	/* Cashe bit indicating need for crosstalk fix */  	switch (hw->mac.type) { @@ -390,6 +392,9 @@ s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)  		status = hw->mac.ops.start_hw(hw);  	} +	/* Initialize the LED link active for LED blink support */ +	hw->mac.ops.init_led_link_act(hw); +  	return status;  } @@ -773,6 +778,49 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)  }  /** + *  ixgbe_init_led_link_act_generic - Store the LED index link/activity. + *  @hw: pointer to hardware structure + * + *  Store the index for the link active LED. This will be used to support + *  blinking the LED. + **/ +s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw) +{ +	struct ixgbe_mac_info *mac = &hw->mac; +	u32 led_reg, led_mode; +	u16 i; + +	led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + +	/* Get LED link active from the LEDCTL register */ +	for (i = 0; i < 4; i++) { +		led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i); + +		if ((led_mode & IXGBE_LED_MODE_MASK_BASE) == +		    IXGBE_LED_LINK_ACTIVE) { +			mac->led_link_act = i; +			return 0; +		} +	} + +	/* If LEDCTL register does not have the LED link active set, then use +	 * known MAC defaults. +	 */ +	switch (hw->mac.type) { +	case ixgbe_mac_x550em_a: +		mac->led_link_act = 0; +		break; +	case ixgbe_mac_X550EM_x: +		mac->led_link_act = 1; +		break; +	default: +		mac->led_link_act = 2; +	} + +	return 0; +} + +/**   *  ixgbe_led_on_generic - Turns on the software controllable LEDs.   *  @hw: pointer to hardware structure   *  @index: led number to turn on @@ -2127,7 +2175,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)  	}  	/* Negotiate the fc mode to use */ -	ixgbe_fc_autoneg(hw); +	hw->mac.ops.fc_autoneg(hw);  	/* Disable any previous flow control settings */  	mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); @@ -2231,8 +2279,8 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)   *  Find the intersection between advertised settings and link partner's   *  advertised settings   **/ -static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, -			      u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) +s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, +		       u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)  {  	if ((!(adv_reg)) ||  (!(lp_reg)))  		return IXGBE_ERR_FC_NOT_NEGOTIATED; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h index 6d4c260d0cbd..5b3e3c65927e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h @@ -49,6 +49,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw);  s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index);  s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index); +s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw);  s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);  s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index f49f80380aa5..fd192bf29b26 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2225,11 +2225,11 @@ static int ixgbe_set_phys_id(struct net_device *netdev,  		return 2;  	case ETHTOOL_ID_ON: -		hw->mac.ops.led_on(hw, hw->bus.func); +		hw->mac.ops.led_on(hw, hw->mac.led_link_act);  		break;  	case ETHTOOL_ID_OFF: -		hw->mac.ops.led_off(hw, hw->bus.func); +		hw->mac.ops.led_off(hw, hw->mac.led_link_act);  		break;  	case ETHTOOL_ID_INACTIVE: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index bd93d823cc25..1e2f39ebd824 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -54,6 +54,7 @@  #include <net/pkt_cls.h>  #include <net/tc_act/tc_gact.h>  #include <net/tc_act/tc_mirred.h> +#include <net/vxlan.h>  #include "ixgbe.h"  #include "ixgbe_common.h" @@ -3070,6 +3071,9 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)  		return;  	} +	if (!adapter->msix_entries) +		return; +  	for (vector = 0; vector < adapter->num_q_vectors; vector++) {  		struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];  		struct msix_entry *entry = &adapter->msix_entries[vector]; @@ -5012,24 +5016,23 @@ fwd_queue_err:  	return err;  } -static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter) +static int ixgbe_upper_dev_walk(struct net_device *upper, void *data)  { -	struct net_device *upper; -	struct list_head *iter; -	int err; +	if (netif_is_macvlan(upper)) { +		struct macvlan_dev *dfwd = netdev_priv(upper); +		struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv; -	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 (dfwd->fwd_priv) { -				err = ixgbe_fwd_ring_up(upper, vadapter); -				if (err) -					continue; -			} -		} +		if (dfwd->fwd_priv) +			ixgbe_fwd_ring_up(upper, vadapter);  	} + +	return 0; +} + +static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter) +{ +	netdev_walk_all_upper_dev_rcu(adapter->netdev, +				      ixgbe_upper_dev_walk, NULL);  }  static void ixgbe_configure(struct ixgbe_adapter *adapter) @@ -5448,12 +5451,25 @@ static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)  	spin_unlock(&adapter->fdir_perfect_lock);  } +static int ixgbe_disable_macvlan(struct net_device *upper, void *data) +{ +	if (netif_is_macvlan(upper)) { +		struct macvlan_dev *vlan = netdev_priv(upper); + +		if (vlan->fwd_priv) { +			netif_tx_stop_all_queues(upper); +			netif_carrier_off(upper); +			netif_tx_disable(upper); +		} +	} + +	return 0; +} +  void ixgbe_down(struct ixgbe_adapter *adapter)  {  	struct net_device *netdev = adapter->netdev;  	struct ixgbe_hw *hw = &adapter->hw; -	struct net_device *upper; -	struct list_head *iter;  	int i;  	/* signal that we are down to the interrupt handler */ @@ -5477,17 +5493,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)  	netif_tx_disable(netdev);  	/* disable any upper devices */ -	netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) { -		if (netif_is_macvlan(upper)) { -			struct macvlan_dev *vlan = netdev_priv(upper); - -			if (vlan->fwd_priv) { -				netif_tx_stop_all_queues(upper); -				netif_carrier_off(upper); -				netif_tx_disable(upper); -			} -		} -	} +	netdev_walk_all_upper_dev_rcu(adapter->netdev, +				      ixgbe_disable_macvlan, NULL);  	ixgbe_irq_disable(adapter); @@ -5618,7 +5625,8 @@ static void ixgbe_init_dcb(struct ixgbe_adapter *adapter)   * Fields are initialized based on PCI device information and   * OS network device settings (MTU size).   **/ -static int ixgbe_sw_init(struct ixgbe_adapter *adapter) +static int ixgbe_sw_init(struct ixgbe_adapter *adapter, +			 const struct ixgbe_info *ii)  {  	struct ixgbe_hw *hw = &adapter->hw;  	struct pci_dev *pdev = adapter->pdev; @@ -5634,6 +5642,9 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)  	hw->subsystem_vendor_id = pdev->subsystem_vendor;  	hw->subsystem_device_id = pdev->subsystem_device; +	/* get_invariants needs the device IDs */ +	ii->get_invariants(hw); +  	/* Set common capability flags and settings */  	rss = min_t(int, ixgbe_max_rss_indices(adapter), num_online_cpus());  	adapter->ring_feature[RING_F_RSS].limit = rss; @@ -6049,11 +6060,6 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)  static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)  {  	struct ixgbe_adapter *adapter = netdev_priv(netdev); -	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - -	/* MTU < 68 is an error and causes problems on some kernels */ -	if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) -		return -EINVAL;  	/*  	 * For 82599EB we cannot allow legacy VFs to enable their receive @@ -6062,7 +6068,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)  	 */  	if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&  	    (adapter->hw.mac.type == ixgbe_mac_82599EB) && -	    (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN))) +	    (new_mtu > ETH_DATA_LEN))  		e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n");  	e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu); @@ -6728,6 +6734,18 @@ static void ixgbe_update_default_up(struct ixgbe_adapter *adapter)  #endif  } +static int ixgbe_enable_macvlan(struct net_device *upper, void *data) +{ +	if (netif_is_macvlan(upper)) { +		struct macvlan_dev *vlan = netdev_priv(upper); + +		if (vlan->fwd_priv) +			netif_tx_wake_all_queues(upper); +	} + +	return 0; +} +  /**   * ixgbe_watchdog_link_is_up - update netif_carrier status and   *                             print link up message @@ -6737,8 +6755,6 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)  {  	struct net_device *netdev = adapter->netdev;  	struct ixgbe_hw *hw = &adapter->hw; -	struct net_device *upper; -	struct list_head *iter;  	u32 link_speed = adapter->link_speed;  	const char *speed_str;  	bool flow_rx, flow_tx; @@ -6809,14 +6825,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)  	/* enable any upper devices */  	rtnl_lock(); -	netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) { -		if (netif_is_macvlan(upper)) { -			struct macvlan_dev *vlan = netdev_priv(upper); - -			if (vlan->fwd_priv) -				netif_tx_wake_all_queues(upper); -		} -	} +	netdev_walk_all_upper_dev_rcu(adapter->netdev, +				      ixgbe_enable_macvlan, NULL);  	rtnl_unlock();  	/* update the default user priority for VFs */ @@ -7277,11 +7287,15 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,  	/* initialize outer IP header fields */  	if (ip.v4->version == 4) { +		unsigned char *csum_start = skb_checksum_start(skb); +		unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); +  		/* IP header will have to cancel out any data that  		 * is not a part of the outer IP header  		 */ -		ip.v4->check = csum_fold(csum_add(lco_csum(skb), -						  csum_unfold(l4.tcp->check))); +		ip.v4->check = csum_fold(csum_partial(trans_start, +						      csum_start - trans_start, +						      0));  		type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;  		ip.v4->tot_len = 0; @@ -7651,11 +7665,17 @@ static void ixgbe_atr(struct ixgbe_ring *ring,  	/* snag network header to get L4 type and address */  	skb = first->skb;  	hdr.network = skb_network_header(skb); +	if (unlikely(hdr.network <= skb->data)) +		return;  	if (skb->encapsulation &&  	    first->protocol == htons(ETH_P_IP) && -	    hdr.ipv4->protocol != IPPROTO_UDP) { +	    hdr.ipv4->protocol == IPPROTO_UDP) {  		struct ixgbe_adapter *adapter = q_vector->adapter; +		if (unlikely(skb_tail_pointer(skb) < hdr.network + +			     VXLAN_HEADROOM)) +			return; +  		/* verify the port is recognized as VXLAN */  		if (adapter->vxlan_port &&  		    udp_hdr(skb)->dest == adapter->vxlan_port) @@ -7666,6 +7686,12 @@ static void ixgbe_atr(struct ixgbe_ring *ring,  			hdr.network = skb_inner_network_header(skb);  	} +	/* Make sure we have at least [minimum IPv4 header + TCP] +	 * or [IPv6 header] bytes +	 */ +	if (unlikely(skb_tail_pointer(skb) < hdr.network + 40)) +		return; +  	/* Currently only IPv4/IPv6 with TCP is supported */  	switch (hdr.ipv4->version) {  	case IPVERSION: @@ -7685,6 +7711,10 @@ static void ixgbe_atr(struct ixgbe_ring *ring,  	if (l4_proto != IPPROTO_TCP)  		return; +	if (unlikely(skb_tail_pointer(skb) < hdr.network + +		     hlen + sizeof(struct tcphdr))) +		return; +  	th = (struct tcphdr *)(hdr.network + hlen);  	/* skip this packet since the socket is closing */ @@ -8350,12 +8380,38 @@ static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter,  }  #ifdef CONFIG_NET_CLS_ACT +struct upper_walk_data { +	struct ixgbe_adapter *adapter; +	u64 action; +	int ifindex; +	u8 queue; +}; + +static int get_macvlan_queue(struct net_device *upper, void *_data) +{ +	if (netif_is_macvlan(upper)) { +		struct macvlan_dev *dfwd = netdev_priv(upper); +		struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv; +		struct upper_walk_data *data = _data; +		struct ixgbe_adapter *adapter = data->adapter; +		int ifindex = data->ifindex; + +		if (vadapter && vadapter->netdev->ifindex == ifindex) { +			data->queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx; +			data->action = data->queue; +			return 1; +		} +	} + +	return 0; +} +  static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,  				  u8 *queue, u64 *action)  {  	unsigned int num_vfs = adapter->num_vfs, vf; +	struct upper_walk_data data;  	struct net_device *upper; -	struct list_head *iter;  	/* redirect to a SRIOV VF */  	for (vf = 0; vf < num_vfs; ++vf) { @@ -8373,17 +8429,16 @@ static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,  	}  	/* 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; -			} -		} +	data.adapter = adapter; +	data.ifindex = ifindex; +	data.action = 0; +	data.queue = 0; +	if (netdev_walk_all_upper_dev_rcu(adapter->netdev, +					  get_macvlan_queue, &data)) { +		*action = data.action; +		*queue = data.queue; + +		return 0;  	}  	return -EINVAL; @@ -8410,7 +8465,7 @@ static int parse_tc_actions(struct ixgbe_adapter *adapter,  		}  		/* Redirect to a VF or a offloaded macvlan */ -		if (is_tcf_mirred_redirect(a)) { +		if (is_tcf_mirred_egress_redirect(a)) {  			int ifindex = tcf_mirred_ifindex(a);  			err = handle_redirect_action(adapter, ifindex, queue, @@ -9477,6 +9532,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	hw->mac.ops   = *ii->mac_ops;  	hw->mac.type  = ii->mac;  	hw->mvals     = ii->mvals; +	if (ii->link_ops) +		hw->link.ops  = *ii->link_ops;  	/* EEPROM */  	hw->eeprom.ops = *ii->eeprom_ops; @@ -9500,10 +9557,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	hw->phy.mdio.mdio_read = ixgbe_mdio_read;  	hw->phy.mdio.mdio_write = ixgbe_mdio_write; -	ii->get_invariants(hw); -  	/* setup the private structure */ -	err = ixgbe_sw_init(adapter); +	err = ixgbe_sw_init(adapter, ii);  	if (err)  		goto err_sw_init; @@ -9612,6 +9667,10 @@ skip_sriov:  	netdev->priv_flags |= IFF_UNICAST_FLT;  	netdev->priv_flags |= IFF_SUPP_NOFCS; +	/* MTU range: 68 - 9710 */ +	netdev->min_mtu = ETH_MIN_MTU; +	netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN); +  #ifdef CONFIG_IXGBE_DCB  	if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE)  		netdev->dcbnl_ops = &dcbnl_ops; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 021ab9b89c71..3b8362085f57 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -109,8 +109,8 @@ static u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2)   *   *  Returns an error code on error.   */ -static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, -					       u16 reg, u16 *val, bool lock) +s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, +					u16 reg, u16 *val, bool lock)  {  	u32 swfw_mask = hw->phy.phy_semaphore_mask;  	int max_retry = 10; @@ -178,36 +178,6 @@ fail:  }  /** - *  ixgbe_read_i2c_combined_generic - Perform I2C read combined operation - *  @hw: pointer to the hardware structure - *  @addr: I2C bus address to read from - *  @reg: I2C device register to read from - *  @val: pointer to location to receive read value - * - *  Returns an error code on error. - */ -s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, -				    u16 reg, u16 *val) -{ -	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); -} - -/** - *  ixgbe_read_i2c_combined_generic_unlocked - Unlocked I2C read combined - *  @hw: pointer to the hardware structure - *  @addr: I2C bus address to read from - *  @reg: I2C device register to read from - *  @val: pointer to location to receive read value - * - *  Returns an error code on error. - */ -s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, -					     u16 reg, u16 *val) -{ -	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); -} - -/**   *  ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation   *  @hw: pointer to the hardware structure   *  @addr: I2C bus address to write to @@ -217,8 +187,8 @@ s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,   *   *  Returns an error code on error.   */ -static s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, -						u16 reg, u16 val, bool lock) +s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, +					 u16 reg, u16 val, bool lock)  {  	u32 swfw_mask = hw->phy.phy_semaphore_mask;  	int max_retry = 1; @@ -273,33 +243,39 @@ fail:  }  /** - *  ixgbe_write_i2c_combined_generic - Perform I2C write combined operation - *  @hw: pointer to the hardware structure - *  @addr: I2C bus address to write to - *  @reg: I2C device register to write to - *  @val: value to write + *  ixgbe_probe_phy - Probe a single address for a PHY + *  @hw: pointer to hardware structure + *  @phy_addr: PHY address to probe   * - *  Returns an error code on error. - */ -s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, -				     u8 addr, u16 reg, u16 val) + *  Returns true if PHY found + **/ +static bool ixgbe_probe_phy(struct ixgbe_hw *hw, u16 phy_addr)  { -	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); -} +	u16 ext_ability = 0; -/** - *  ixgbe_write_i2c_combined_generic_unlocked - Unlocked I2C write combined - *  @hw: pointer to the hardware structure - *  @addr: I2C bus address to write to - *  @reg: I2C device register to write to - *  @val: value to write - * - *  Returns an error code on error. - */ -s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, -					      u8 addr, u16 reg, u16 val) -{ -	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); +	hw->phy.mdio.prtad = phy_addr; +	if (mdio45_probe(&hw->phy.mdio, phy_addr) != 0) +		return false; + +	if (ixgbe_get_phy_id(hw)) +		return false; + +	hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id); + +	if (hw->phy.type == ixgbe_phy_unknown) { +		hw->phy.ops.read_reg(hw, +				     MDIO_PMA_EXTABLE, +				     MDIO_MMD_PMAPMD, +				     &ext_ability); +		if (ext_ability & +		    (MDIO_PMA_EXTABLE_10GBT | +		     MDIO_PMA_EXTABLE_1000BT)) +			hw->phy.type = ixgbe_phy_cu_unknown; +		else +			hw->phy.type = ixgbe_phy_generic; +	} + +	return true;  }  /** @@ -311,7 +287,7 @@ s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,  s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)  {  	u32 phy_addr; -	u16 ext_ability = 0; +	u32 status = IXGBE_ERR_PHY_ADDR_INVALID;  	if (!hw->phy.phy_semaphore_mask) {  		if (hw->bus.lan_id) @@ -320,37 +296,34 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)  			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;  	} -	if (hw->phy.type == ixgbe_phy_unknown) { -		for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { -			hw->phy.mdio.prtad = phy_addr; -			if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) { -				ixgbe_get_phy_id(hw); -				hw->phy.type = -					ixgbe_get_phy_type_from_id(hw->phy.id); - -				if (hw->phy.type == ixgbe_phy_unknown) { -					hw->phy.ops.read_reg(hw, -							     MDIO_PMA_EXTABLE, -							     MDIO_MMD_PMAPMD, -							     &ext_ability); -					if (ext_ability & -					    (MDIO_PMA_EXTABLE_10GBT | -					     MDIO_PMA_EXTABLE_1000BT)) -						hw->phy.type = -							 ixgbe_phy_cu_unknown; -					else -						hw->phy.type = -							 ixgbe_phy_generic; -				} +	if (hw->phy.type != ixgbe_phy_unknown) +		return 0; -				return 0; -			} +	if (hw->phy.nw_mng_if_sel) { +		phy_addr = (hw->phy.nw_mng_if_sel & +			    IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> +			   IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; +		if (ixgbe_probe_phy(hw, phy_addr)) +			return 0; +		else +			return IXGBE_ERR_PHY_ADDR_INVALID; +	} + +	for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { +		if (ixgbe_probe_phy(hw, phy_addr)) { +			status = 0; +			break;  		} -		/* indicate no PHY found */ -		hw->phy.mdio.prtad = MDIO_PRTAD_NONE; -		return IXGBE_ERR_PHY_ADDR_INVALID;  	} -	return 0; + +	/* Certain media types do not have a phy so an address will not +	 * be found and the code will take this path.  Caller has to +	 * decide if it is an error or not. +	 */ +	if (status) +		hw->phy.mdio.prtad = MDIO_PRTAD_NONE; + +	return status;  }  /** @@ -416,7 +389,8 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)  	case TN1010_PHY_ID:  		phy_type = ixgbe_phy_tn;  		break; -	case X550_PHY_ID: +	case X550_PHY_ID2: +	case X550_PHY_ID3:  	case X540_PHY_ID:  		phy_type = ixgbe_phy_aq;  		break; @@ -427,6 +401,7 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)  		phy_type = ixgbe_phy_nl;  		break;  	case X557_PHY_ID: +	case X557_PHY_ID2:  		phy_type = ixgbe_phy_x550em_ext_t;  		break;  	default: @@ -477,8 +452,7 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)  	 */  	for (i = 0; i < 30; i++) {  		msleep(100); -		hw->phy.ops.read_reg(hw, MDIO_CTRL1, -				     MDIO_MMD_PHYXS, &ctrl); +		hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &ctrl);  		if (!(ctrl & MDIO_CTRL1_RESET)) {  			udelay(2);  			break; @@ -705,53 +679,52 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)  	ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); -	if (speed & IXGBE_LINK_SPEED_10GB_FULL) { -		/* Set or unset auto-negotiation 10G advertisement */ -		hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, -				     MDIO_MMD_AN, -				     &autoneg_reg); +	/* Set or unset auto-negotiation 10G advertisement */ +	hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, &autoneg_reg); -		autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G; -		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) -			autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G; - -		hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL, -				      MDIO_MMD_AN, -				      autoneg_reg); -	} +	autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G; +	if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) && +	    (speed & IXGBE_LINK_SPEED_10GB_FULL)) +		autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G; -	if (speed & IXGBE_LINK_SPEED_1GB_FULL) { -		/* Set or unset auto-negotiation 1G advertisement */ -		hw->phy.ops.read_reg(hw, -				     IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, -				     MDIO_MMD_AN, -				     &autoneg_reg); +	hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, autoneg_reg); -		autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE; -		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) -			autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE; +	hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, +			     MDIO_MMD_AN, &autoneg_reg); -		hw->phy.ops.write_reg(hw, -				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, -				      MDIO_MMD_AN, -				      autoneg_reg); +	if (hw->mac.type == ixgbe_mac_X550) { +		/* Set or unset auto-negotiation 5G advertisement */ +		autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE; +		if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) && +		    (speed & IXGBE_LINK_SPEED_5GB_FULL)) +			autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE; + +		/* Set or unset auto-negotiation 2.5G advertisement */ +		autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE; +		if ((hw->phy.autoneg_advertised & +		     IXGBE_LINK_SPEED_2_5GB_FULL) && +		    (speed & IXGBE_LINK_SPEED_2_5GB_FULL)) +			autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE;  	} -	if (speed & IXGBE_LINK_SPEED_100_FULL) { -		/* Set or unset auto-negotiation 100M advertisement */ -		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, -				     MDIO_MMD_AN, -				     &autoneg_reg); +	/* Set or unset auto-negotiation 1G advertisement */ +	autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE; +	if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) && +	    (speed & IXGBE_LINK_SPEED_1GB_FULL)) +		autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE; -		autoneg_reg &= ~(ADVERTISE_100FULL | -				 ADVERTISE_100HALF); -		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) -			autoneg_reg |= ADVERTISE_100FULL; +	hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, +			      MDIO_MMD_AN, autoneg_reg); -		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, -				      MDIO_MMD_AN, -				      autoneg_reg); -	} +	/* Set or unset auto-negotiation 100M advertisement */ +	hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg); + +	autoneg_reg &= ~(ADVERTISE_100FULL | ADVERTISE_100HALF); +	if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) && +	    (speed & IXGBE_LINK_SPEED_100_FULL)) +		autoneg_reg |= ADVERTISE_100FULL; + +	hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg);  	/* Blocked by MNG FW so don't reset PHY */  	if (ixgbe_check_reset_blocked(hw)) @@ -830,6 +803,7 @@ static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw)  		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;  		break;  	case ixgbe_mac_X550EM_x: +	case ixgbe_mac_x550em_a:  		hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;  		break;  	default: @@ -2396,9 +2370,7 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on)  	if (!on && ixgbe_mng_present(hw))  		return 0; -	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, -				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, -				      ®); +	status = hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, ®);  	if (status)  		return status; @@ -2410,8 +2382,6 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on)  		reg |= IXGBE_MDIO_PHY_SET_LOW_POWER_MODE;  	} -	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, -				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, -				       reg); +	status = hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, reg);  	return status;  } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index cc735ec3e045..ecf05f838fc5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -195,12 +195,8 @@ s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset,  				   u8 *sff8472_data);  s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,  				   u8 eeprom_data); -s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, -				    u16 reg, u16 *val); -s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, -					     u16 reg, u16 *val); -s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, -				     u16 reg, u16 val); -s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, -					      u16 reg, u16 val); +s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg, +					u16 *val, bool lock); +s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg, +					 u16 val, bool lock);  #endif /* _IXGBE_PHY_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 31d82e3abac8..cf21273db201 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -874,19 +874,13 @@ struct ixgbe_thermal_sensor_data {  #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB	0x4 /* 1Gb/s */  #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB	0x6 /* 10Gb/s */ -#define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG	0x20	/* 10G Control Reg */  #define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400	/* 1G Provisioning 1 */  #define IXGBE_MII_AUTONEG_XNP_TX_REG		0x17	/* 1G XNP Transmit */ -#define IXGBE_MII_AUTONEG_ADVERTISE_REG		0x10	/* 100M Advertisement */ -#define IXGBE_MII_10GBASE_T_ADVERTISE		0x1000	/* full duplex, bit:12*/  #define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX	0x4000	/* full duplex, bit:14*/  #define IXGBE_MII_1GBASE_T_ADVERTISE		0x8000	/* full duplex, bit:15*/  #define IXGBE_MII_2_5GBASE_T_ADVERTISE		0x0400  #define IXGBE_MII_5GBASE_T_ADVERTISE		0x0800 -#define IXGBE_MII_100BASE_T_ADVERTISE		0x0100	/* full duplex, bit:8 */ -#define IXGBE_MII_100BASE_T_ADVERTISE_HALF	0x0080	/* half duplex, bit:7 */  #define IXGBE_MII_RESTART			0x200 -#define IXGBE_MII_AUTONEG_COMPLETE		0x20  #define IXGBE_MII_AUTONEG_LINK_UP		0x04  #define IXGBE_MII_AUTONEG_REG			0x0 @@ -1320,30 +1314,20 @@ struct ixgbe_thermal_sensor_data {  /* MDIO definitions */  #define IXGBE_MDIO_ZERO_DEV_TYPE		0x0 -#define IXGBE_MDIO_PMA_PMD_DEV_TYPE		0x1  #define IXGBE_MDIO_PCS_DEV_TYPE		0x3 -#define IXGBE_MDIO_PHY_XS_DEV_TYPE		0x4 -#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE		0x7 -#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE	0x1E   /* Device 30 */  #define IXGBE_TWINAX_DEV			1  #define IXGBE_MDIO_COMMAND_TIMEOUT     100 /* PHY Timeout for 1 GB mode */ -#define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL      0x0    /* VS1 Control Reg */ -#define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS       0x1    /* VS1 Status Reg */  #define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS  0x0008 /* 1 = Link Up */  #define IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS 0x0010 /* 0 - 10G, 1 - 1G */  #define IXGBE_MDIO_VENDOR_SPECIFIC_1_10G_SPEED    0x0018  #define IXGBE_MDIO_VENDOR_SPECIFIC_1_1G_SPEED     0x0010 -#define IXGBE_MDIO_AUTO_NEG_CONTROL	0x0 /* AUTO_NEG Control Reg */ -#define IXGBE_MDIO_AUTO_NEG_STATUS	0x1 /* AUTO_NEG Status Reg */  #define IXGBE_MDIO_AUTO_NEG_VENDOR_STAT	0xC800 /* AUTO_NEG Vendor Status Reg */  #define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM  0xCC00 /* AUTO_NEG Vendor TX Reg */  #define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2 0xCC01 /* AUTO_NEG Vendor Tx Reg */  #define IXGBE_MDIO_AUTO_NEG_VEN_LSC	0x1 /* AUTO_NEG Vendor Tx LSC */ -#define IXGBE_MDIO_AUTO_NEG_ADVT	0x10 /* AUTO_NEG Advt Reg */ -#define IXGBE_MDIO_AUTO_NEG_LP		0x13 /* AUTO_NEG LP Status Reg */  #define IXGBE_MDIO_AUTO_NEG_EEE_ADVT	0x3C /* AUTO_NEG EEE Advt Reg */  #define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE	 0x0800 /* Set low power mode */ @@ -1393,8 +1377,10 @@ struct ixgbe_thermal_sensor_data {  #define TN1010_PHY_ID    0x00A19410  #define TNX_FW_REV       0xB  #define X540_PHY_ID      0x01540200 -#define X550_PHY_ID      0x01540220 +#define X550_PHY_ID2	0x01540223 +#define X550_PHY_ID3	0x01540221  #define X557_PHY_ID      0x01540240 +#define X557_PHY_ID2	0x01540250  #define QT2022_PHY_ID    0x0043A400  #define ATH_PHY_ID       0x03429050  #define AQ_FW_REV        0x20 @@ -3352,6 +3338,7 @@ struct ixgbe_mac_operations {  	s32 (*led_off)(struct ixgbe_hw *, u32);  	s32 (*blink_led_start)(struct ixgbe_hw *, u32);  	s32 (*blink_led_stop)(struct ixgbe_hw *, u32); +	s32 (*init_led_link_act)(struct ixgbe_hw *);  	/* RAR, Multicast, VLAN */  	s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32); @@ -3372,6 +3359,7 @@ struct ixgbe_mac_operations {  	/* Flow Control */  	s32 (*fc_enable)(struct ixgbe_hw *);  	s32 (*setup_fc)(struct ixgbe_hw *); +	void (*fc_autoneg)(struct ixgbe_hw *);  	/* Manageability interface */  	s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8); @@ -3410,16 +3398,28 @@ struct ixgbe_phy_operations {  	s32 (*read_i2c_sff8472)(struct ixgbe_hw *, u8 , u8 *);  	s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);  	s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8); -	s32 (*read_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val); -	s32 (*write_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);  	s32 (*check_overtemp)(struct ixgbe_hw *);  	s32 (*set_phy_power)(struct ixgbe_hw *, bool on);  	s32 (*enter_lplu)(struct ixgbe_hw *);  	s32 (*handle_lasi)(struct ixgbe_hw *hw); -	s32 (*read_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, -					  u16 *value); -	s32 (*write_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, -					   u16 value); +	s32 (*read_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr, +				      u8 *value); +	s32 (*write_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr, +				       u8 value); +}; + +struct ixgbe_link_operations { +	s32 (*read_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val); +	s32 (*read_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, +				  u16 *val); +	s32 (*write_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val); +	s32 (*write_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, +				   u16 val); +}; + +struct ixgbe_link_info { +	struct ixgbe_link_operations ops; +	u8 addr;  };  struct ixgbe_eeprom_info { @@ -3462,6 +3462,7 @@ struct ixgbe_mac_info {  	u8				san_mac_rar_index;  	struct ixgbe_thermal_sensor_data  thermal_sensor_data;  	bool				set_lben; +	u8				led_link_act;  };  struct ixgbe_phy_info { @@ -3523,6 +3524,7 @@ struct ixgbe_hw {  	struct ixgbe_addr_filter_info	addr_ctrl;  	struct ixgbe_fc_info		fc;  	struct ixgbe_phy_info		phy; +	struct ixgbe_link_info		link;  	struct ixgbe_eeprom_info	eeprom;  	struct ixgbe_bus_info		bus;  	struct ixgbe_mbx_info		mbx; @@ -3546,6 +3548,7 @@ struct ixgbe_info {  	const struct ixgbe_eeprom_operations	*eeprom_ops;  	const struct ixgbe_phy_operations	*phy_ops;  	const struct ixgbe_mbx_operations	*mbx_ops; +	const struct ixgbe_link_operations	*link_ops;  	const u32			*mvals;  }; @@ -3593,17 +3596,35 @@ struct ixgbe_info {  #define IXGBE_FUSES0_REV_MASK		(3u << 6)  #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P)	((P) ? 0x8010 : 0x4010) +#define IXGBE_KRM_LINK_S1(P)		((P) ? 0x8200 : 0x4200)  #define IXGBE_KRM_LINK_CTRL_1(P)	((P) ? 0x820C : 0x420C)  #define IXGBE_KRM_AN_CNTL_1(P)		((P) ? 0x822C : 0x422C)  #define IXGBE_KRM_AN_CNTL_8(P)		((P) ? 0x8248 : 0x4248)  #define IXGBE_KRM_SGMII_CTRL(P)		((P) ? 0x82A0 : 0x42A0) +#define IXGBE_KRM_LP_BASE_PAGE_HIGH(P)	((P) ? 0x836C : 0x436C)  #define IXGBE_KRM_DSP_TXFFE_STATE_4(P)	((P) ? 0x8634 : 0x4634)  #define IXGBE_KRM_DSP_TXFFE_STATE_5(P)	((P) ? 0x8638 : 0x4638)  #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P)	((P) ? 0x8B00 : 0x4B00)  #define IXGBE_KRM_PMD_DFX_BURNIN(P)	((P) ? 0x8E00 : 0x4E00) +#define IXGBE_KRM_PMD_FLX_MASK_ST20(P)	((P) ? 0x9054 : 0x5054)  #define IXGBE_KRM_TX_COEFF_CTRL_1(P)	((P) ? 0x9520 : 0x5520)  #define IXGBE_KRM_RX_ANA_CTL(P)		((P) ? 0x9A00 : 0x5A00) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA		~(0x3 << 20) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR		BIT(20) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_LR		(0x2 << 20) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN		BIT(25) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN		BIT(26) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN		BIT(27) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10M		~(0x7 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_100M		BIT(28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G		(0x2 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G		(0x3 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN		(0x4 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_2_5G		(0x7 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK		(0x7 << 28) +#define IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART	BIT(31) +  #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B		BIT(9)  #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS		BIT(11) @@ -3618,6 +3639,7 @@ struct ixgbe_info {  #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR		BIT(18)  #define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX		BIT(24)  #define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR		BIT(26) +#define IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE		BIT(28)  #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE		BIT(29)  #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART		BIT(31) @@ -3627,6 +3649,8 @@ struct ixgbe_info {  #define IXGBE_KRM_AN_CNTL_8_LINEAR			BIT(0)  #define IXGBE_KRM_AN_CNTL_8_LIMITING			BIT(1) +#define IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE		BIT(10) +#define IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE		BIT(11)  #define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D	BIT(12)  #define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D		BIT(19) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index f2b1d48a16c3..e2ff823ee202 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -851,6 +851,7 @@ static const struct ixgbe_mac_operations mac_ops_X540 = {  	.get_link_capabilities  = &ixgbe_get_copper_link_capabilities_generic,  	.led_on                 = &ixgbe_led_on_generic,  	.led_off                = &ixgbe_led_off_generic, +	.init_led_link_act	= ixgbe_init_led_link_act_generic,  	.blink_led_start        = &ixgbe_blink_led_start_X540,  	.blink_led_stop         = &ixgbe_blink_led_stop_X540,  	.set_rar                = &ixgbe_set_rar_generic, @@ -866,6 +867,7 @@ static const struct ixgbe_mac_operations mac_ops_X540 = {  	.set_vfta               = &ixgbe_set_vfta_generic,  	.fc_enable              = &ixgbe_fc_enable_generic,  	.setup_fc		= ixgbe_setup_fc_generic, +	.fc_autoneg		= ixgbe_fc_autoneg,  	.set_fw_drv_ver         = &ixgbe_set_fw_drv_ver_generic,  	.init_uta_tables        = &ixgbe_init_uta_tables_generic,  	.setup_sfp              = NULL, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 7e6b9267ca9d..11fb433eb924 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -28,11 +28,31 @@  static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed);  static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *); +static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *); +static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *); +static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *);  static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw)  {  	struct ixgbe_mac_info *mac = &hw->mac;  	struct ixgbe_phy_info *phy = &hw->phy; +	struct ixgbe_link_info *link = &hw->link; + +	/* Start with X540 invariants, since so simular */ +	ixgbe_get_invariants_X540(hw); + +	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) +		phy->ops.set_phy_power = NULL; + +	link->addr = IXGBE_CS4227; + +	return 0; +} + +static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw) +{ +	struct ixgbe_mac_info *mac = &hw->mac; +	struct ixgbe_phy_info *phy = &hw->phy;  	/* Start with X540 invariants, since so simular */  	ixgbe_get_invariants_X540(hw); @@ -69,8 +89,7 @@ static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)   */  static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)  { -	return hw->phy.ops.read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, -						      value); +	return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);  }  /** @@ -83,8 +102,7 @@ static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)   */  static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)  { -	return hw->phy.ops.write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, -						       value); +	return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);  }  /** @@ -322,6 +340,68 @@ static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,  	return IXGBE_NOT_IMPLEMENTED;  } +/** + * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to read from + * @reg: I2C device register to read from + * @val: pointer to location to receive read value + * + * Returns an error code on error. + **/ +static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, +					   u16 reg, u16 *val) +{ +	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); +} + +/** + * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to read from + * @reg: I2C device register to read from + * @val: pointer to location to receive read value + * + * Returns an error code on error. + **/ +static s32 +ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, +					 u16 reg, u16 *val) +{ +	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); +} + +/** + * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to write to + * @reg: I2C device register to write to + * @val: value to write + * + * Returns an error code on error. + **/ +static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, +					    u8 addr, u16 reg, u16 val) +{ +	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); +} + +/** + * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to write to + * @reg: I2C device register to write to + * @val: value to write + * + * Returns an error code on error. + **/ +static s32 +ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, +					  u8 addr, u16 reg, u16 val) +{ +	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); +} +  /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params   *  @hw: pointer to hardware structure   * @@ -1128,47 +1208,17 @@ out:  	return ret;  } -/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. +/** + *  ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration   *  @hw: pointer to hardware structure - *  @speed: the link speed to force   * - *  Configures the integrated KR PHY to use iXFI mode. Used to connect an - *  internal and external PHY at a specific speed, without autonegotiation. + *  iXfI configuration needed for ixgbe_mac_X550EM_x devices.   **/ -static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) +static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)  {  	s32 status;  	u32 reg_val; -	/* Disable AN and force speed to 10G Serial. */ -	status = ixgbe_read_iosf_sb_reg_x550(hw, -					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), -					IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); -	if (status) -		return status; - -	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; -	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; - -	/* Select forced link speed for internal PHY. */ -	switch (*speed) { -	case IXGBE_LINK_SPEED_10GB_FULL: -		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; -		break; -	case IXGBE_LINK_SPEED_1GB_FULL: -		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; -		break; -	default: -		/* Other link speeds are not supported by internal KR PHY. */ -		return IXGBE_ERR_LINK_SETUP; -	} - -	status = ixgbe_write_iosf_sb_reg_x550(hw, -				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), -				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -	if (status) -		return status; -  	/* Disable training protocol FSM. */  	status = ixgbe_read_iosf_sb_reg_x550(hw,  				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), @@ -1228,20 +1278,106 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)  	status = ixgbe_write_iosf_sb_reg_x550(hw,  				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),  				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -	if (status) +	return status; +} + +/** + *  ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the + *  internal PHY + *  @hw: pointer to hardware structure + **/ +static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) +{ +	s32 status; +	u32 link_ctrl; + +	/* Restart auto-negotiation. */ +	status = hw->mac.ops.read_iosf_sb_reg(hw, +				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); + +	if (status) { +		hw_dbg(hw, "Auto-negotiation did not complete\n");  		return status; +	} -	/* Toggle port SW reset by AN reset. */ -	status = ixgbe_read_iosf_sb_reg_x550(hw, +	link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; +	status = hw->mac.ops.write_iosf_sb_reg(hw,  				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), -				IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +				IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); + +	if (hw->mac.type == ixgbe_mac_x550em_a) { +		u32 flx_mask_st20; + +		/* Indicate to FW that AN restart has been asserted */ +		status = hw->mac.ops.read_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); + +		if (status) { +			hw_dbg(hw, "Auto-negotiation did not complete\n"); +			return status; +		} + +		flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; +		status = hw->mac.ops.write_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); +	} + +	return status; +} + +/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. + *  @hw: pointer to hardware structure + *  @speed: the link speed to force + * + *  Configures the integrated KR PHY to use iXFI mode. Used to connect an + *  internal and external PHY at a specific speed, without autonegotiation. + **/ +static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) +{ +	s32 status; +	u32 reg_val; + +	/* Disable AN and force speed to 10G Serial. */ +	status = ixgbe_read_iosf_sb_reg_x550(hw, +					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +					IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);  	if (status)  		return status; -	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; +	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; +	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; + +	/* Select forced link speed for internal PHY. */ +	switch (*speed) { +	case IXGBE_LINK_SPEED_10GB_FULL: +		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; +		break; +	case IXGBE_LINK_SPEED_1GB_FULL: +		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; +		break; +	default: +		/* Other link speeds are not supported by internal KR PHY. */ +		return IXGBE_ERR_LINK_SETUP; +	} +  	status = ixgbe_write_iosf_sb_reg_x550(hw,  				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),  				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +	if (status) +		return status; + +	/* Additional configuration needed for x550em_x */ +	if (hw->mac.type == ixgbe_mac_X550EM_x) { +		status = ixgbe_setup_ixfi_x550em_x(hw); +		if (status) +			return status; +	} + +	/* Toggle port SW reset by AN reset. */ +	status = ixgbe_restart_an_internal_phy_x550em(hw);  	return status;  } @@ -1292,7 +1428,7 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,  				__always_unused bool autoneg_wait_to_complete)  {  	s32 status; -	u16 slice, value; +	u16 reg_slice, reg_val;  	bool setup_linear = false;  	/* Check if SFP module is supported and linear */ @@ -1308,71 +1444,68 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,  	if (status)  		return status; -	if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { -		/* Configure CS4227 LINE side to 10G SR. */ -		slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); -		value = IXGBE_CS4227_SPEED_10G; -		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -							  slice, value); -		if (status) -			goto i2c_err; +	/* Configure internal PHY for KR/KX. */ +	ixgbe_setup_kr_speed_x550em(hw, speed); -		slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); -		value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; -		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -							  slice, value); -		if (status) -			goto i2c_err; - -		/* Configure CS4227 for HOST connection rate then type. */ -		slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); -		value = speed & IXGBE_LINK_SPEED_10GB_FULL ? -			IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; -		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -							  slice, value); -		if (status) -			goto i2c_err; +	/* Configure CS4227 LINE side to proper mode. */ +	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); +	if (setup_linear) +		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; +	else +		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; -		slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); -		if (setup_linear) -			value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; -		else -			value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; -		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -							  slice, value); -		if (status) -			goto i2c_err; +	status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, +					 reg_val); -		/* Setup XFI internal link. */ -		status = ixgbe_setup_ixfi_x550em(hw, &speed); -		if (status) { -			hw_dbg(hw, "setup_ixfi failed with %d\n", status); -			return status; -		} -	} else { -		/* Configure internal PHY for KR/KX. */ -		status = ixgbe_setup_kr_speed_x550em(hw, speed); -		if (status) { -			hw_dbg(hw, "setup_kr_speed failed with %d\n", status); -			return status; -		} +	return status; +} -		/* Configure CS4227 LINE side to proper mode. */ -		slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); -		if (setup_linear) -			value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; -		else -			value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; -		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -							  slice, value); -		if (status) -			goto i2c_err; +/** + * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode + * @hw: pointer to hardware structure + * @speed: the link speed to force + * + * Configures the integrated PHY for native SFI mode. Used to connect the + * internal PHY directly to an SFP cage, without autonegotiation. + **/ +static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) +{ +	struct ixgbe_mac_info *mac = &hw->mac; +	s32 status; +	u32 reg_val; + +	/* Disable all AN and force speed to 10G Serial. */ +	status = mac->ops.read_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +	if (status) +		return status; + +	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; +	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; +	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; +	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; + +	/* Select forced link speed for internal PHY. */ +	switch (*speed) { +	case IXGBE_LINK_SPEED_10GB_FULL: +		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; +		break; +	case IXGBE_LINK_SPEED_1GB_FULL: +		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; +		break; +	default: +		/* Other link speeds are not supported by internal PHY. */ +		return IXGBE_ERR_LINK_SETUP;  	} -	return 0; +	status = mac->ops.write_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + +	/* Toggle port SW reset by AN reset. */ +	status = ixgbe_restart_an_internal_phy_x550em(hw); -i2c_err: -	hw_dbg(hw, "combined i2c access failed with %d\n", status);  	return status;  } @@ -1388,45 +1521,39 @@ ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed,  {  	bool setup_linear = false;  	u32 reg_phy_int; -	s32 rc; +	s32 ret_val;  	/* Check if SFP module is supported and linear */ -	rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); +	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);  	/* If no SFP module present, then return success. Return success since  	 * SFP not present error is not excepted in the setup MAC link flow.  	 */ -	if (rc == IXGBE_ERR_SFP_NOT_PRESENT) +	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)  		return 0; -	if (!rc) -		return rc; +	if (!ret_val) +		return ret_val; -	/* Configure internal PHY for native SFI */ -	rc = hw->mac.ops.read_iosf_sb_reg(hw, -					  IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), -					  IXGBE_SB_IOSF_TARGET_KR_PHY, -					  ®_phy_int); -	if (rc) -		return rc; +	/* Configure internal PHY for native SFI based on module type */ +	ret_val = hw->mac.ops.read_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); +	if (!ret_val) +		return ret_val; -	if (setup_linear) { -		reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING; -		reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR; -	} else { -		reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING; -		reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR; -	} +	reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; +	if (!setup_linear) +		reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; -	rc = hw->mac.ops.write_iosf_sb_reg(hw, -					   IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), -					   IXGBE_SB_IOSF_TARGET_KR_PHY, -					   reg_phy_int); -	if (rc) -		return rc; +	ret_val = hw->mac.ops.write_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); +	if (!ret_val) +		return ret_val; -	/* Setup XFI/SFI internal link */ -	return ixgbe_setup_ixfi_x550em(hw, &speed); +	/* Setup SFI internal link. */ +	return ixgbe_setup_sfi_x550a(hw, &speed);  }  /** @@ -1442,19 +1569,19 @@ ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed,  	u32 reg_slice, slice_offset;  	bool setup_linear = false;  	u16 reg_phy_ext; -	s32 rc; +	s32 ret_val;  	/* Check if SFP module is supported and linear */ -	rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); +	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);  	/* If no SFP module present, then return success. Return success since  	 * SFP not present error is not excepted in the setup MAC link flow.  	 */ -	if (rc == IXGBE_ERR_SFP_NOT_PRESENT) +	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)  		return 0; -	if (!rc) -		return rc; +	if (!ret_val) +		return ret_val;  	/* Configure internal PHY for KR/KX. */  	ixgbe_setup_kr_speed_x550em(hw, speed); @@ -1463,10 +1590,10 @@ ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed,  		return IXGBE_ERR_PHY_ADDR_INVALID;  	/* Get external PHY device id */ -	rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, +	ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB,  				  IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); -	if (rc) -		return rc; +	if (ret_val) +		return ret_val;  	/* When configuring quad port CS4223, the MAC instance is part  	 * of the slice offset. @@ -1538,7 +1665,7 @@ static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw,  				     bool link_up_wait_to_complete)  {  	u32 status; -	u16 autoneg_status; +	u16 i, autoneg_status;  	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)  		return IXGBE_ERR_CONFIG; @@ -1550,14 +1677,18 @@ static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw,  	if (status || !(*link_up))  		return status; -	 /* MAC link is up, so check external PHY link. -	  * Read this twice back to back to indicate current status. -	  */ -	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, -				      &autoneg_status); -	if (status) -		return status; +	/* MAC link is up, so check external PHY link. +	 * Link status is latching low, and can only be used to detect link +	 * drop, and not the current status of the link without performing +	 * back-to-back reads. +	 */ +	for (i = 0; i < 2; i++) { +		status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, +					      &autoneg_status); + +		if (status) +			return status; +	}  	/* If external PHY link is not up, then indicate link not up */  	if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) @@ -1575,7 +1706,7 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed,  		  __always_unused bool autoneg_wait_to_complete)  {  	struct ixgbe_mac_info *mac = &hw->mac; -	u32 lval, sval; +	u32 lval, sval, flx_val;  	s32 rc;  	rc = mac->ops.read_iosf_sb_reg(hw, @@ -1609,14 +1740,55 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed,  	if (rc)  		return rc; -	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; +	rc = mac->ops.read_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); +	if (rc) +		return rc; + +	rc = mac->ops.read_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); +	if (rc) +		return rc; + +	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; +	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; +	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; +	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; +	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; +  	rc = mac->ops.write_iosf_sb_reg(hw, -					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), -					IXGBE_SB_IOSF_TARGET_KR_PHY, lval); +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); +	if (rc) +		return rc; +	rc = ixgbe_restart_an_internal_phy_x550em(hw);  	return rc;  } +/** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers + *  @hw: pointer to hardware structure + **/ +static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw) +{ +	struct ixgbe_mac_info *mac = &hw->mac; + +	switch (mac->ops.get_media_type(hw)) { +	case ixgbe_media_type_fiber: +		mac->ops.setup_fc = NULL; +		mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; +		break; +	case ixgbe_media_type_backplane: +		mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; +		mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; +		break; +	default: +		break; +	} +} +  /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers   *  @hw: pointer to hardware structure   **/ @@ -1664,6 +1836,10 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)  	default:  		break;  	} + +	/* Additional modification for X550em_a devices */ +	if (hw->mac.type == ixgbe_mac_x550em_a) +		ixgbe_init_mac_link_ops_X550em_a(hw);  }  /** ixgbe_setup_sfp_modules_X550em - Setup SFP module @@ -1740,7 +1916,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)  	/* Vendor alarm triggered */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, -				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +				      MDIO_MMD_VEND1,  				      ®);  	if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) @@ -1748,7 +1924,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)  	/* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, -				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +				      MDIO_MMD_VEND1,  				      ®);  	if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | @@ -1757,7 +1933,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)  	/* Global alarm triggered */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, -				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +				      MDIO_MMD_VEND1,  				      ®);  	if (status) @@ -1772,7 +1948,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)  	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {  		/*  device fault alarm triggered */  		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, -					  IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +					  MDIO_MMD_VEND1,  					  ®);  		if (status)  			return status; @@ -1787,14 +1963,14 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)  	/* Vendor alarm 2 triggered */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); +				      MDIO_MMD_AN, ®);  	if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))  		return status;  	/* link connect/disconnect event occurred */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); +				      MDIO_MMD_AN, ®);  	if (status)  		return status; @@ -1826,20 +2002,20 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)  	/* Enable link status change alarm */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); +				      MDIO_MMD_AN, ®);  	if (status)  		return status;  	reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;  	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, -				       IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); +				       MDIO_MMD_AN, reg);  	if (status)  		return status;  	/* Enable high temperature failure and global fault alarms */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, -				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +				      MDIO_MMD_VEND1,  				      ®);  	if (status)  		return status; @@ -1848,14 +2024,14 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)  		IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);  	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, -				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +				       MDIO_MMD_VEND1,  				       reg);  	if (status)  		return status;  	/* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, -				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +				      MDIO_MMD_VEND1,  				      ®);  	if (status)  		return status; @@ -1864,14 +2040,14 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)  		IXGBE_MDIO_GLOBAL_ALARM_1_INT);  	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, -				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +				       MDIO_MMD_VEND1,  				       reg);  	if (status)  		return status;  	/* Enable chip-wide vendor alarm */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, -				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +				      MDIO_MMD_VEND1,  				      ®);  	if (status)  		return status; @@ -1879,7 +2055,7 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)  	reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;  	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, -				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +				       MDIO_MMD_VEND1,  				       reg);  	return status; @@ -1945,13 +2121,31 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,  	if (speed & IXGBE_LINK_SPEED_1GB_FULL)  		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; -	/* Restart auto-negotiation. */ -	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;  	status = hw->mac.ops.write_iosf_sb_reg(hw,  					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),  					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -	return status; +	if (hw->mac.type == ixgbe_mac_x550em_a) { +		/* Set lane mode  to KR auto negotiation */ +		status = hw->mac.ops.read_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + +		if (status) +			return status; + +		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; +		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; +		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; +		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; +		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; + +		status = hw->mac.ops.write_iosf_sb_reg(hw, +				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +	} + +	return ixgbe_restart_an_internal_phy_x550em(hw);  }  /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. @@ -2020,14 +2214,12 @@ static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)  	*link_up = false;  	/* read this twice back to back to indicate current status */ -	ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, -				   IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,  				   &autoneg_status);  	if (ret)  		return ret; -	ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, -				   IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,  				   &autoneg_status);  	if (ret)  		return ret; @@ -2073,7 +2265,7 @@ static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)  		return 0;  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +				      MDIO_MMD_AN,  				      &speed);  	if (status)  		return status; @@ -2134,10 +2326,10 @@ static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx)  	/* To turn on the LED, set mode to ON. */  	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, -			     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); +			     MDIO_MMD_VEND1, &phy_data);  	phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;  	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, -			      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); +			      MDIO_MMD_VEND1, phy_data);  	return 0;  } @@ -2156,10 +2348,10 @@ static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx)  	/* To turn on the LED, set mode to ON. */  	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, -			     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); +			     MDIO_MMD_VEND1, &phy_data);  	phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;  	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, -			      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); +			      MDIO_MMD_VEND1, phy_data);  	return 0;  } @@ -2180,7 +2372,7 @@ static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw,  	*lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;  	status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +				      MDIO_MMD_AN,  				      &an_lp_status);  	if (status)  		return status; @@ -2281,6 +2473,90 @@ static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw)  	return rc;  } +/** + *  ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 + *  @hw: pointer to hardware structure + **/ +static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) +{ +	u32 link_s1, lp_an_page_low, an_cntl_1; +	s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; +	ixgbe_link_speed speed; +	bool link_up; + +	/* AN should have completed when the cable was plugged in. +	 * Look for reasons to bail out.  Bail out if: +	 * - FC autoneg is disabled, or if +	 * - link is not up. +	 */ +	if (hw->fc.disable_fc_autoneg) { +		hw_err(hw, "Flow control autoneg is disabled"); +		goto out; +	} + +	hw->mac.ops.check_link(hw, &speed, &link_up, false); +	if (!link_up) { +		hw_err(hw, "The link is down"); +		goto out; +	} + +	/* Check at auto-negotiation has completed */ +	status = hw->mac.ops.read_iosf_sb_reg(hw, +					IXGBE_KRM_LINK_S1(hw->bus.lan_id), +					IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); + +	if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { +		hw_dbg(hw, "Auto-Negotiation did not complete\n"); +		status = IXGBE_ERR_FC_NOT_NEGOTIATED; +		goto out; +	} + +	/* Read the 10g AN autoc and LP ability registers and resolve +	 * local flow control settings accordingly +	 */ +	status = hw->mac.ops.read_iosf_sb_reg(hw, +				IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); + +	if (status) { +		hw_dbg(hw, "Auto-Negotiation did not complete\n"); +		goto out; +	} + +	status = hw->mac.ops.read_iosf_sb_reg(hw, +				IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), +				IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); + +	if (status) { +		hw_dbg(hw, "Auto-Negotiation did not complete\n"); +		goto out; +	} + +	status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low, +				    IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, +				    IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, +				    IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, +				    IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); + +out: +	if (!status) { +		hw->fc.fc_was_autonegged = true; +	} else { +		hw->fc.fc_was_autonegged = false; +		hw->fc.current_mode = hw->fc.requested_mode; +	} +} + +/** + *  ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings + *  @hw: pointer to hardware structure + **/ +static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) +{ +	hw->fc.fc_was_autonegged = false; +	hw->fc.current_mode = hw->fc.requested_mode; +} +  /** ixgbe_enter_lplu_x550em - Transition to low power states   *  @hw: pointer to hardware structure   * @@ -2327,7 +2603,7 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)  		return ixgbe_set_copper_phy_power(hw, false);  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +				      MDIO_MMD_AN,  				      &speed);  	if (status)  		return status; @@ -2349,20 +2625,20 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)  	/* Clear AN completed indication */  	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +				      MDIO_MMD_AN,  				      &autoneg_reg);  	if (status)  		return status; -	status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +	status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, +				      MDIO_MMD_AN,  				      &an_10g_cntl_reg);  	if (status)  		return status;  	status = hw->phy.ops.read_reg(hw,  				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, -				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +				      MDIO_MMD_AN,  				      &autoneg_reg);  	if (status)  		return status; @@ -2520,7 +2796,7 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)  	status = hw->phy.ops.read_reg(hw,  				      IXGBE_MDIO_TX_VENDOR_ALARMS_3, -				      IXGBE_MDIO_PMA_PMD_DEV_TYPE, +				      MDIO_MMD_PMAPMD,  				      ®);  	if (status)  		return status; @@ -2531,7 +2807,7 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)  	if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {  		status = hw->phy.ops.read_reg(hw,  					IXGBE_MDIO_GLOBAL_RES_PR_10, -					IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +					MDIO_MMD_VEND1,  					®);  		if (status)  			return status; @@ -2540,7 +2816,7 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)  		status = hw->phy.ops.write_reg(hw,  					IXGBE_MDIO_GLOBAL_RES_PR_10, -					IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +					MDIO_MMD_VEND1,  					reg);  		if (status)  			return status; @@ -2729,6 +3005,90 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,  }  /** + *  ixgbe_setup_fc_backplane_x550em_a - Set up flow control + *  @hw: pointer to hardware structure + * + *  Called at init time to set up flow control. + **/ +static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) +{ +	s32 status = 0; +	u32 an_cntl = 0; + +	/* Validate the requested mode */ +	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { +		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); +		return IXGBE_ERR_INVALID_LINK_SETTINGS; +	} + +	if (hw->fc.requested_mode == ixgbe_fc_default) +		hw->fc.requested_mode = ixgbe_fc_full; + +	/* Set up the 1G and 10G flow control advertisement registers so the +	 * HW will be able to do FC autoneg once the cable is plugged in.  If +	 * we link at 10G, the 1G advertisement is harmless and vice versa. +	 */ +	status = hw->mac.ops.read_iosf_sb_reg(hw, +					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), +					IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); + +	if (status) { +		hw_dbg(hw, "Auto-Negotiation did not complete\n"); +		return status; +	} + +	/* The possible values of fc.requested_mode are: +	 * 0: Flow control is completely disabled +	 * 1: Rx flow control is enabled (we can receive pause frames, +	 *    but not send pause frames). +	 * 2: Tx flow control is enabled (we can send pause frames but +	 *    we do not support receiving pause frames). +	 * 3: Both Rx and Tx flow control (symmetric) are enabled. +	 * other: Invalid. +	 */ +	switch (hw->fc.requested_mode) { +	case ixgbe_fc_none: +		/* Flow control completely disabled by software override. */ +		an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | +			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); +		break; +	case ixgbe_fc_tx_pause: +		/* Tx Flow control is enabled, and Rx Flow control is +		 * disabled by software override. +		 */ +		an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; +		an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; +		break; +	case ixgbe_fc_rx_pause: +		/* Rx Flow control is enabled and Tx Flow control is +		 * disabled by software override. Since there really +		 * isn't a way to advertise that we are capable of RX +		 * Pause ONLY, we will advertise that we support both +		 * symmetric and asymmetric Rx PAUSE, as such we fall +		 * through to the fc_full statement.  Later, we will +		 * disable the adapter's ability to send PAUSE frames. +		 */ +	case ixgbe_fc_full: +		/* Flow control (both Rx and Tx) is enabled by SW override. */ +		an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | +			   IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; +		break; +	default: +		hw_err(hw, "Flow control param set incorrectly\n"); +		return IXGBE_ERR_CONFIG; +	} + +	status = hw->mac.ops.write_iosf_sb_reg(hw, +					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), +					IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); + +	/* Restart auto-negotiation. */ +	status = ixgbe_restart_an_internal_phy_x550em(hw); + +	return status; +} + +/**   * ixgbe_set_mux - Set mux for port 1 access with CS4227   * @hw: pointer to hardware structure   * @state: set mux if 1, clear if 0 @@ -2934,6 +3294,7 @@ static const struct ixgbe_mac_operations mac_ops_X550 = {  	X550_COMMON_MAC  	.led_on			= ixgbe_led_on_generic,  	.led_off		= ixgbe_led_off_generic, +	.init_led_link_act	= ixgbe_init_led_link_act_generic,  	.reset_hw		= &ixgbe_reset_hw_X540,  	.get_media_type		= &ixgbe_get_media_type_X540,  	.get_san_mac_addr	= &ixgbe_get_san_mac_addr_generic, @@ -2948,12 +3309,14 @@ static const struct ixgbe_mac_operations mac_ops_X550 = {  	.prot_autoc_read	= prot_autoc_read_generic,  	.prot_autoc_write	= prot_autoc_write_generic,  	.setup_fc		= ixgbe_setup_fc_generic, +	.fc_autoneg		= ixgbe_fc_autoneg,  };  static const struct ixgbe_mac_operations mac_ops_X550EM_x = {  	X550_COMMON_MAC  	.led_on			= ixgbe_led_on_t_x550em,  	.led_off		= ixgbe_led_off_t_x550em, +	.init_led_link_act	= ixgbe_init_led_link_act_generic,  	.reset_hw		= &ixgbe_reset_hw_X550em,  	.get_media_type		= &ixgbe_get_media_type_X550em,  	.get_san_mac_addr	= NULL, @@ -2966,6 +3329,7 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = {  	.release_swfw_sync	= &ixgbe_release_swfw_sync_X550em,  	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,  	.setup_fc		= NULL, /* defined later */ +	.fc_autoneg		= ixgbe_fc_autoneg,  	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550,  	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550,  }; @@ -2974,6 +3338,7 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = {  	X550_COMMON_MAC  	.led_on			= ixgbe_led_on_t_x550em,  	.led_off		= ixgbe_led_off_t_x550em, +	.init_led_link_act	= ixgbe_init_led_link_act_generic,  	.reset_hw		= ixgbe_reset_hw_X550em,  	.get_media_type		= ixgbe_get_media_type_X550em,  	.get_san_mac_addr	= NULL, @@ -2985,6 +3350,7 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = {  	.acquire_swfw_sync	= ixgbe_acquire_swfw_sync_x550em_a,  	.release_swfw_sync	= ixgbe_release_swfw_sync_x550em_a,  	.setup_fc		= ixgbe_setup_fc_x550em, +	.fc_autoneg		= ixgbe_fc_autoneg,  	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550a,  	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550a,  }; @@ -3036,11 +3402,6 @@ static const struct ixgbe_phy_operations phy_ops_X550EM_x = {  	.identify		= &ixgbe_identify_phy_x550em,  	.read_reg		= &ixgbe_read_phy_reg_generic,  	.write_reg		= &ixgbe_write_phy_reg_generic, -	.read_i2c_combined	= &ixgbe_read_i2c_combined_generic, -	.write_i2c_combined	= &ixgbe_write_i2c_combined_generic, -	.read_i2c_combined_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, -	.write_i2c_combined_unlocked = -				     &ixgbe_write_i2c_combined_generic_unlocked,  };  static const struct ixgbe_phy_operations phy_ops_x550em_a = { @@ -3053,6 +3414,13 @@ static const struct ixgbe_phy_operations phy_ops_x550em_a = {  	.write_reg_mdi		= &ixgbe_write_phy_reg_mdi,  }; +static const struct ixgbe_link_operations link_ops_x550em_x = { +	.read_link		= &ixgbe_read_i2c_combined_generic, +	.read_link_unlocked	= &ixgbe_read_i2c_combined_generic_unlocked, +	.write_link		= &ixgbe_write_i2c_combined_generic, +	.write_link_unlocked	= &ixgbe_write_i2c_combined_generic_unlocked, +}; +  static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = {  	IXGBE_MVALS_INIT(X550)  }; @@ -3083,11 +3451,12 @@ const struct ixgbe_info ixgbe_X550EM_x_info = {  	.phy_ops		= &phy_ops_X550EM_x,  	.mbx_ops		= &mbx_ops_generic,  	.mvals			= ixgbe_mvals_X550EM_x, +	.link_ops		= &link_ops_x550em_x,  };  const struct ixgbe_info ixgbe_x550em_a_info = {  	.mac			= ixgbe_mac_x550em_a, -	.get_invariants		= &ixgbe_get_invariants_X550_x, +	.get_invariants		= &ixgbe_get_invariants_X550_a,  	.mac_ops		= &mac_ops_x550em_a,  	.eeprom_ops		= &eeprom_ops_X550EM_x,  	.phy_ops		= &phy_ops_x550em_a, diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 7eaac3234049..6d4bef5803f2 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -1498,6 +1498,9 @@ static void ixgbevf_free_irq(struct ixgbevf_adapter *adapter)  {  	int i, q_vectors; +	if (!adapter->msix_entries) +		return; +  	q_vectors = adapter->num_msix_vectors;  	i = q_vectors - 1; @@ -2552,6 +2555,9 @@ static void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter)   **/  static void ixgbevf_reset_interrupt_capability(struct ixgbevf_adapter *adapter)  { +	if (!adapter->msix_entries) +		return; +  	pci_disable_msix(adapter->pdev);  	kfree(adapter->msix_entries);  	adapter->msix_entries = NULL; @@ -3329,11 +3335,15 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,  	/* initialize outer IP header fields */  	if (ip.v4->version == 4) { +		unsigned char *csum_start = skb_checksum_start(skb); +		unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); +  		/* IP header will have to cancel out any data that  		 * is not a part of the outer IP header  		 */ -		ip.v4->check = csum_fold(csum_add(lco_csum(skb), -						  csum_unfold(l4.tcp->check))); +		ip.v4->check = csum_fold(csum_partial(trans_start, +						      csum_start - trans_start, +						      0));  		type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;  		ip.v4->tot_len = 0; @@ -3742,24 +3752,8 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)  	struct ixgbevf_adapter *adapter = netdev_priv(netdev);  	struct ixgbe_hw *hw = &adapter->hw;  	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; -	int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;  	int ret; -	switch (adapter->hw.api_version) { -	case ixgbe_mbox_api_11: -	case ixgbe_mbox_api_12: -		max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE; -		break; -	default: -		if (adapter->hw.mac.type != ixgbe_mac_82599_vf) -			max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE; -		break; -	} - -	/* MTU < 68 is an error and causes problems on some kernels */ -	if ((new_mtu < 68) || (max_frame > max_possible_frame)) -		return -EINVAL; -  	spin_lock_bh(&adapter->mbx_lock);  	/* notify the PF of our intent to use this size of frame */  	ret = hw->mac.ops.set_rlpml(hw, max_frame); @@ -3810,11 +3804,10 @@ static int ixgbevf_suspend(struct pci_dev *pdev, pm_message_t state)  		ixgbevf_free_irq(adapter);  		ixgbevf_free_all_tx_resources(adapter);  		ixgbevf_free_all_rx_resources(adapter); +		ixgbevf_clear_interrupt_scheme(adapter);  		rtnl_unlock();  	} -	ixgbevf_clear_interrupt_scheme(adapter); -  #ifdef CONFIG_PM  	retval = pci_save_state(pdev);  	if (retval) @@ -4104,6 +4097,23 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	netdev->priv_flags |= IFF_UNICAST_FLT; +	/* MTU range: 68 - 1504 or 9710 */ +	netdev->min_mtu = ETH_MIN_MTU; +	switch (adapter->hw.api_version) { +	case ixgbe_mbox_api_11: +	case ixgbe_mbox_api_12: +		netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - +				  (ETH_HLEN + ETH_FCS_LEN); +		break; +	default: +		if (adapter->hw.mac.type != ixgbe_mac_82599_vf) +			netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - +					  (ETH_HLEN + ETH_FCS_LEN); +		else +			netdev->max_mtu = ETH_DATA_LEN + ETH_FCS_LEN; +		break; +	} +  	if (IXGBE_REMOVED(hw->hw_addr)) {  		err = -EIO;  		goto err_sw_init; |