diff options
Diffstat (limited to 'drivers/net/ethernet/intel')
26 files changed, 346 insertions, 228 deletions
| diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.c b/drivers/net/ethernet/intel/i40e/i40e_diag.c index 5b3519c6e362..97fe1787a8f4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_diag.c +++ b/drivers/net/ethernet/intel/i40e/i40e_diag.c @@ -44,7 +44,7 @@ static int i40e_diag_reg_pattern_test(struct i40e_hw *hw,  	return 0;  } -struct i40e_diag_reg_test_info i40e_reg_list[] = { +const struct i40e_diag_reg_test_info i40e_reg_list[] = {  	/* offset               mask         elements   stride */  	{I40E_QTX_CTL(0),       0x0000FFBF, 1,  		I40E_QTX_CTL(1) - I40E_QTX_CTL(0)}, @@ -78,27 +78,28 @@ int i40e_diag_reg_test(struct i40e_hw *hw)  {  	int ret_code = 0;  	u32 reg, mask; +	u32 elements;  	u32 i, j;  	for (i = 0; i40e_reg_list[i].offset != 0 &&  					     !ret_code; i++) { +		elements = i40e_reg_list[i].elements;  		/* set actual reg range for dynamically allocated resources */  		if (i40e_reg_list[i].offset == I40E_QTX_CTL(0) &&  		    hw->func_caps.num_tx_qp != 0) -			i40e_reg_list[i].elements = hw->func_caps.num_tx_qp; +			elements = hw->func_caps.num_tx_qp;  		if ((i40e_reg_list[i].offset == I40E_PFINT_ITRN(0, 0) ||  		     i40e_reg_list[i].offset == I40E_PFINT_ITRN(1, 0) ||  		     i40e_reg_list[i].offset == I40E_PFINT_ITRN(2, 0) ||  		     i40e_reg_list[i].offset == I40E_QINT_TQCTL(0) ||  		     i40e_reg_list[i].offset == I40E_QINT_RQCTL(0)) &&  		    hw->func_caps.num_msix_vectors != 0) -			i40e_reg_list[i].elements = -				hw->func_caps.num_msix_vectors - 1; +			elements = hw->func_caps.num_msix_vectors - 1;  		/* test register access */  		mask = i40e_reg_list[i].mask; -		for (j = 0; j < i40e_reg_list[i].elements && !ret_code; j++) { +		for (j = 0; j < elements && !ret_code; j++) {  			reg = i40e_reg_list[i].offset +  			      (j * i40e_reg_list[i].stride);  			ret_code = i40e_diag_reg_pattern_test(hw, reg, mask); diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.h b/drivers/net/ethernet/intel/i40e/i40e_diag.h index e641035c7297..c3ce5f35211f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_diag.h +++ b/drivers/net/ethernet/intel/i40e/i40e_diag.h @@ -20,7 +20,7 @@ struct i40e_diag_reg_test_info {  	u32 stride;	/* bytes between each element */  }; -extern struct i40e_diag_reg_test_info i40e_reg_list[]; +extern const struct i40e_diag_reg_test_info i40e_reg_list[];  int i40e_diag_reg_test(struct i40e_hw *hw);  int i40e_diag_eeprom_test(struct i40e_hw *hw); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 467001db5070..228cd502bb48 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -15525,6 +15525,7 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)  	int err;  	int v_idx; +	pci_set_drvdata(pf->pdev, pf);  	pci_save_state(pf->pdev);  	/* set up periodic task facility */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 924f972b91fa..72b091f2509d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -171,10 +171,10 @@ static char *i40e_create_dummy_packet(u8 *dummy_packet, bool ipv4, u8 l4proto,  				      struct i40e_fdir_filter *data)  {  	bool is_vlan = !!data->vlan_tag; -	struct vlan_hdr vlan; -	struct ipv6hdr ipv6; -	struct ethhdr eth; -	struct iphdr ip; +	struct vlan_hdr vlan = {}; +	struct ipv6hdr ipv6 = {}; +	struct ethhdr eth = {}; +	struct iphdr ip = {};  	u8 *tmp;  	if (ipv4) { diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h index 232bc61d9eee..746ff76f2fb1 100644 --- a/drivers/net/ethernet/intel/iavf/iavf.h +++ b/drivers/net/ethernet/intel/iavf/iavf.h @@ -59,8 +59,6 @@ enum iavf_vsi_state_t {  struct iavf_vsi {  	struct iavf_adapter *back;  	struct net_device *netdev; -	unsigned long active_cvlans[BITS_TO_LONGS(VLAN_N_VID)]; -	unsigned long active_svlans[BITS_TO_LONGS(VLAN_N_VID)];  	u16 seid;  	u16 id;  	DECLARE_BITMAP(state, __IAVF_VSI_STATE_SIZE__); @@ -158,15 +156,20 @@ struct iavf_vlan {  	u16 tpid;  }; +enum iavf_vlan_state_t { +	IAVF_VLAN_INVALID, +	IAVF_VLAN_ADD,		/* filter needs to be added */ +	IAVF_VLAN_IS_NEW,	/* filter is new, wait for PF answer */ +	IAVF_VLAN_ACTIVE,	/* filter is accepted by PF */ +	IAVF_VLAN_DISABLE,	/* filter needs to be deleted by PF, then marked INACTIVE */ +	IAVF_VLAN_INACTIVE,	/* filter is inactive, we are in IFF_DOWN */ +	IAVF_VLAN_REMOVE,	/* filter needs to be removed from list */ +}; +  struct iavf_vlan_filter {  	struct list_head list;  	struct iavf_vlan vlan; -	struct { -		u8 is_new_vlan:1;	/* filter is new, wait for PF answer */ -		u8 remove:1;		/* filter needs to be removed */ -		u8 add:1;		/* filter needs to be added */ -		u8 padding:5; -	}; +	enum iavf_vlan_state_t state;  };  #define IAVF_MAX_TRAFFIC_CLASS	4 @@ -258,6 +261,7 @@ struct iavf_adapter {  	wait_queue_head_t vc_waitqueue;  	struct iavf_q_vector *q_vectors;  	struct list_head vlan_filter_list; +	int num_vlan_filters;  	struct list_head mac_filter_list;  	struct mutex crit_lock;  	struct mutex client_lock; diff --git a/drivers/net/ethernet/intel/iavf/iavf_common.c b/drivers/net/ethernet/intel/iavf/iavf_common.c index 16c490965b61..dd11dbbd5551 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_common.c +++ b/drivers/net/ethernet/intel/iavf/iavf_common.c @@ -661,7 +661,7 @@ struct iavf_rx_ptype_decoded iavf_ptype_lookup[BIT(8)] = {  	/* Non Tunneled IPv6 */  	IAVF_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3),  	IAVF_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3), -	IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP,  PAY3), +	IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP,  PAY4),  	IAVF_PTT_UNUSED_ENTRY(91),  	IAVF_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP,  PAY4),  	IAVF_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4), diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 3273aeb8fa67..2de4baff4c20 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -791,7 +791,8 @@ iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter,  		f->vlan = vlan;  		list_add_tail(&f->list, &adapter->vlan_filter_list); -		f->add = true; +		f->state = IAVF_VLAN_ADD; +		adapter->num_vlan_filters++;  		adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;  	} @@ -813,7 +814,7 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, struct iavf_vlan vlan)  	f = iavf_find_vlan(adapter, vlan);  	if (f) { -		f->remove = true; +		f->state = IAVF_VLAN_REMOVE;  		adapter->aq_required |= IAVF_FLAG_AQ_DEL_VLAN_FILTER;  	} @@ -828,14 +829,18 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, struct iavf_vlan vlan)   **/  static void iavf_restore_filters(struct iavf_adapter *adapter)  { -	u16 vid; +	struct iavf_vlan_filter *f;  	/* re-add all VLAN filters */ -	for_each_set_bit(vid, adapter->vsi.active_cvlans, VLAN_N_VID) -		iavf_add_vlan(adapter, IAVF_VLAN(vid, ETH_P_8021Q)); +	spin_lock_bh(&adapter->mac_vlan_list_lock); + +	list_for_each_entry(f, &adapter->vlan_filter_list, list) { +		if (f->state == IAVF_VLAN_INACTIVE) +			f->state = IAVF_VLAN_ADD; +	} -	for_each_set_bit(vid, adapter->vsi.active_svlans, VLAN_N_VID) -		iavf_add_vlan(adapter, IAVF_VLAN(vid, ETH_P_8021AD)); +	spin_unlock_bh(&adapter->mac_vlan_list_lock); +	adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;  }  /** @@ -844,8 +849,7 @@ static void iavf_restore_filters(struct iavf_adapter *adapter)   */  u16 iavf_get_num_vlans_added(struct iavf_adapter *adapter)  { -	return bitmap_weight(adapter->vsi.active_cvlans, VLAN_N_VID) + -		bitmap_weight(adapter->vsi.active_svlans, VLAN_N_VID); +	return adapter->num_vlan_filters;  }  /** @@ -893,6 +897,10 @@ static int iavf_vlan_rx_add_vid(struct net_device *netdev,  {  	struct iavf_adapter *adapter = netdev_priv(netdev); +	/* Do not track VLAN 0 filter, always added by the PF on VF init */ +	if (!vid) +		return 0; +  	if (!VLAN_FILTERING_ALLOWED(adapter))  		return -EIO; @@ -919,12 +927,11 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev,  {  	struct iavf_adapter *adapter = netdev_priv(netdev); -	iavf_del_vlan(adapter, IAVF_VLAN(vid, be16_to_cpu(proto))); -	if (proto == cpu_to_be16(ETH_P_8021Q)) -		clear_bit(vid, adapter->vsi.active_cvlans); -	else -		clear_bit(vid, adapter->vsi.active_svlans); +	/* We do not track VLAN 0 filter */ +	if (!vid) +		return 0; +	iavf_del_vlan(adapter, IAVF_VLAN(vid, be16_to_cpu(proto)));  	return 0;  } @@ -1285,16 +1292,11 @@ static void iavf_clear_mac_vlan_filters(struct iavf_adapter *adapter)  		}  	} -	/* remove all VLAN filters */ +	/* disable all VLAN filters */  	list_for_each_entry_safe(vlf, vlftmp, &adapter->vlan_filter_list, -				 list) { -		if (vlf->add) { -			list_del(&vlf->list); -			kfree(vlf); -		} else { -			vlf->remove = true; -		} -	} +				 list) +		vlf->state = IAVF_VLAN_DISABLE; +  	spin_unlock_bh(&adapter->mac_vlan_list_lock);  } @@ -2906,6 +2908,7 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)  		list_del(&fv->list);  		kfree(fv);  	} +	adapter->num_vlan_filters = 0;  	spin_unlock_bh(&adapter->mac_vlan_list_lock); @@ -3123,9 +3126,6 @@ continue_reset:  	adapter->aq_required |= IAVF_FLAG_AQ_ADD_CLOUD_FILTER;  	iavf_misc_irq_enable(adapter); -	bitmap_clear(adapter->vsi.active_cvlans, 0, VLAN_N_VID); -	bitmap_clear(adapter->vsi.active_svlans, 0, VLAN_N_VID); -  	mod_delayed_work(adapter->wq, &adapter->watchdog_task, 2);  	/* We were running when the reset started, so we need to restore some @@ -5066,6 +5066,11 @@ static void iavf_remove(struct pci_dev *pdev)  			mutex_unlock(&adapter->crit_lock);  			break;  		} +		/* Simply return if we already went through iavf_shutdown */ +		if (adapter->state == __IAVF_REMOVE) { +			mutex_unlock(&adapter->crit_lock); +			return; +		}  		mutex_unlock(&adapter->crit_lock);  		usleep_range(500, 1000); diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c index 18b6a702a1d6..e989feda133c 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c @@ -1096,7 +1096,7 @@ static inline void iavf_rx_hash(struct iavf_ring *ring,  		cpu_to_le64((u64)IAVF_RX_DESC_FLTSTAT_RSS_HASH <<  			    IAVF_RX_DESC_STATUS_FLTSTAT_SHIFT); -	if (ring->netdev->features & NETIF_F_RXHASH) +	if (!(ring->netdev->features & NETIF_F_RXHASH))  		return;  	if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) { diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index 6d23338604bb..9afbbdac3590 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -642,16 +642,10 @@ static void iavf_vlan_add_reject(struct iavf_adapter *adapter)  	spin_lock_bh(&adapter->mac_vlan_list_lock);  	list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { -		if (f->is_new_vlan) { -			if (f->vlan.tpid == ETH_P_8021Q) -				clear_bit(f->vlan.vid, -					  adapter->vsi.active_cvlans); -			else -				clear_bit(f->vlan.vid, -					  adapter->vsi.active_svlans); - +		if (f->state == IAVF_VLAN_IS_NEW) {  			list_del(&f->list);  			kfree(f); +			adapter->num_vlan_filters--;  		}  	}  	spin_unlock_bh(&adapter->mac_vlan_list_lock); @@ -679,7 +673,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter)  	spin_lock_bh(&adapter->mac_vlan_list_lock);  	list_for_each_entry(f, &adapter->vlan_filter_list, list) { -		if (f->add) +		if (f->state == IAVF_VLAN_ADD)  			count++;  	}  	if (!count || !VLAN_FILTERING_ALLOWED(adapter)) { @@ -710,11 +704,10 @@ void iavf_add_vlans(struct iavf_adapter *adapter)  		vvfl->vsi_id = adapter->vsi_res->vsi_id;  		vvfl->num_elements = count;  		list_for_each_entry(f, &adapter->vlan_filter_list, list) { -			if (f->add) { +			if (f->state == IAVF_VLAN_ADD) {  				vvfl->vlan_id[i] = f->vlan.vid;  				i++; -				f->add = false; -				f->is_new_vlan = true; +				f->state = IAVF_VLAN_IS_NEW;  				if (i == count)  					break;  			} @@ -760,7 +753,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter)  		vvfl_v2->vport_id = adapter->vsi_res->vsi_id;  		vvfl_v2->num_elements = count;  		list_for_each_entry(f, &adapter->vlan_filter_list, list) { -			if (f->add) { +			if (f->state == IAVF_VLAN_ADD) {  				struct virtchnl_vlan_supported_caps *filtering_support =  					&adapter->vlan_v2_caps.filtering.filtering_support;  				struct virtchnl_vlan *vlan; @@ -778,8 +771,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter)  				vlan->tpid = f->vlan.tpid;  				i++; -				f->add = false; -				f->is_new_vlan = true; +				f->state = IAVF_VLAN_IS_NEW;  			}  		} @@ -822,10 +814,16 @@ void iavf_del_vlans(struct iavf_adapter *adapter)  		 * filters marked for removal to enable bailing out before  		 * sending a virtchnl message  		 */ -		if (f->remove && !VLAN_FILTERING_ALLOWED(adapter)) { +		if (f->state == IAVF_VLAN_REMOVE && +		    !VLAN_FILTERING_ALLOWED(adapter)) {  			list_del(&f->list);  			kfree(f); -		} else if (f->remove) { +			adapter->num_vlan_filters--; +		} else if (f->state == IAVF_VLAN_DISABLE && +		    !VLAN_FILTERING_ALLOWED(adapter)) { +			f->state = IAVF_VLAN_INACTIVE; +		} else if (f->state == IAVF_VLAN_REMOVE || +			   f->state == IAVF_VLAN_DISABLE) {  			count++;  		}  	} @@ -857,11 +855,18 @@ void iavf_del_vlans(struct iavf_adapter *adapter)  		vvfl->vsi_id = adapter->vsi_res->vsi_id;  		vvfl->num_elements = count;  		list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { -			if (f->remove) { +			if (f->state == IAVF_VLAN_DISABLE) {  				vvfl->vlan_id[i] = f->vlan.vid; +				f->state = IAVF_VLAN_INACTIVE;  				i++; +				if (i == count) +					break; +			} else if (f->state == IAVF_VLAN_REMOVE) { +				vvfl->vlan_id[i] = f->vlan.vid;  				list_del(&f->list);  				kfree(f); +				adapter->num_vlan_filters--; +				i++;  				if (i == count)  					break;  			} @@ -901,7 +906,8 @@ void iavf_del_vlans(struct iavf_adapter *adapter)  		vvfl_v2->vport_id = adapter->vsi_res->vsi_id;  		vvfl_v2->num_elements = count;  		list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { -			if (f->remove) { +			if (f->state == IAVF_VLAN_DISABLE || +			    f->state == IAVF_VLAN_REMOVE) {  				struct virtchnl_vlan_supported_caps *filtering_support =  					&adapter->vlan_v2_caps.filtering.filtering_support;  				struct virtchnl_vlan *vlan; @@ -915,8 +921,13 @@ void iavf_del_vlans(struct iavf_adapter *adapter)  				vlan->tci = f->vlan.vid;  				vlan->tpid = f->vlan.tpid; -				list_del(&f->list); -				kfree(f); +				if (f->state == IAVF_VLAN_DISABLE) { +					f->state = IAVF_VLAN_INACTIVE; +				} else { +					list_del(&f->list); +					kfree(f); +					adapter->num_vlan_filters--; +				}  				i++;  				if (i == count)  					break; @@ -2192,7 +2203,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,  				list_for_each_entry(vlf,  						    &adapter->vlan_filter_list,  						    list) -					vlf->add = true; +					vlf->state = IAVF_VLAN_ADD;  				adapter->aq_required |=  					IAVF_FLAG_AQ_ADD_VLAN_FILTER; @@ -2260,7 +2271,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,  				list_for_each_entry(vlf,  						    &adapter->vlan_filter_list,  						    list) -					vlf->add = true; +					vlf->state = IAVF_VLAN_ADD;  				aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;  			} @@ -2444,17 +2455,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,  		spin_lock_bh(&adapter->mac_vlan_list_lock);  		list_for_each_entry(f, &adapter->vlan_filter_list, list) { -			if (f->is_new_vlan) { -				f->is_new_vlan = false; -				if (!f->vlan.vid) -					continue; -				if (f->vlan.tpid == ETH_P_8021Q) -					set_bit(f->vlan.vid, -						adapter->vsi.active_cvlans); -				else -					set_bit(f->vlan.vid, -						adapter->vsi.active_svlans); -			} +			if (f->state == IAVF_VLAN_IS_NEW) +				f->state = IAVF_VLAN_ACTIVE;  		}  		spin_unlock_bh(&adapter->mac_vlan_list_lock);  		} diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index b0e29e342401..e809249500e1 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -509,6 +509,7 @@ enum ice_pf_flags {  	ICE_FLAG_VF_VLAN_PRUNING,  	ICE_FLAG_LINK_LENIENT_MODE_ENA,  	ICE_FLAG_PLUG_AUX_DEV, +	ICE_FLAG_UNPLUG_AUX_DEV,  	ICE_FLAG_MTU_CHANGED,  	ICE_FLAG_GNSS,			/* GNSS successfully initialized */  	ICE_PF_FLAGS_NBITS		/* must be last */ @@ -955,16 +956,11 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf)   */  static inline void ice_clear_rdma_cap(struct ice_pf *pf)  { -	/* We can directly unplug aux device here only if the flag bit -	 * ICE_FLAG_PLUG_AUX_DEV is not set because ice_unplug_aux_dev() -	 * could race with ice_plug_aux_dev() called from -	 * ice_service_task(). In this case we only clear that bit now and -	 * aux device will be unplugged later once ice_plug_aux_device() -	 * called from ice_service_task() finishes (see ice_service_task()). +	/* defer unplug to service task to avoid RTNL lock and +	 * clear PLUG bit so that pending plugs don't interfere  	 */ -	if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) -		ice_unplug_aux_dev(pf); - +	clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags); +	set_bit(ICE_FLAG_UNPLUG_AUX_DEV, pf->flags);  	clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);  }  #endif /* _ICE_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_dcb.c b/drivers/net/ethernet/intel/ice/ice_dcb.c index c557dfc50aad..396e555023aa 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb.c @@ -1411,7 +1411,7 @@ ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)  	tlv->ouisubtype = htonl(ouisubtype);  	buf[0] = dcbcfg->pfc.pfccap & 0xF; -	buf[1] = dcbcfg->pfc.pfcena & 0xF; +	buf[1] = dcbcfg->pfc.pfcena;  }  /** diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index b360bd8f1599..f86e814354a3 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -4331,6 +4331,8 @@ ice_get_module_eeprom(struct net_device *netdev,  		 * SFP modules only ever use page 0.  		 */  		if (page == 0 || !(data[0x2] & 0x4)) { +			u32 copy_len; +  			/* If i2c bus is busy due to slow page change or  			 * link management access, call can fail. This is normal.  			 * So we retry this a few times. @@ -4354,8 +4356,8 @@ ice_get_module_eeprom(struct net_device *netdev,  			}  			/* Make sure we have enough room for the new block */ -			if ((i + SFF_READ_BLOCK_SIZE) < ee->len) -				memcpy(data + i, value, SFF_READ_BLOCK_SIZE); +			copy_len = min_t(u32, SFF_READ_BLOCK_SIZE, ee->len - i); +			memcpy(data + i, value, copy_len);  		}  	}  	return 0; diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 781475480ff2..450317dfcca7 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -291,6 +291,7 @@ static void ice_vsi_delete_from_hw(struct ice_vsi *vsi)  	struct ice_vsi_ctx *ctxt;  	int status; +	ice_fltr_remove_all(vsi);  	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);  	if (!ctxt)  		return; @@ -2126,7 +2127,7 @@ int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi)  	ice_for_each_rxq(vsi, i)  		ice_tx_xsk_pool(vsi, i); -	return ret; +	return 0;  }  /** @@ -2693,12 +2694,14 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)  		return ret;  	/* allocate memory for Tx/Rx ring stat pointers */ -	if (ice_vsi_alloc_stat_arrays(vsi)) +	ret = ice_vsi_alloc_stat_arrays(vsi); +	if (ret)  		goto unroll_vsi_alloc;  	ice_alloc_fd_res(vsi); -	if (ice_vsi_get_qs(vsi)) { +	ret = ice_vsi_get_qs(vsi); +	if (ret) {  		dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n",  			vsi->idx);  		goto unroll_vsi_alloc_stat; @@ -2811,6 +2814,7 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)  		break;  	default:  		/* clean up the resources and exit */ +		ret = -EINVAL;  		goto unroll_vsi_init;  	} @@ -2889,7 +2893,6 @@ void ice_vsi_decfg(struct ice_vsi *vsi)  	    !test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))  		ice_cfg_sw_lldp(vsi, false, false); -	ice_fltr_remove_all(vsi);  	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);  	err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);  	if (err) @@ -3508,10 +3511,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags)  		if (vsi_flags & ICE_VSI_FLAG_INIT) {  			ret = -EIO;  			goto err_vsi_cfg_tc_lan; -		} else { -			kfree(coalesce); -			return ice_schedule_reset(pf, ICE_RESET_PFR);  		} + +		kfree(coalesce); +		return ice_schedule_reset(pf, ICE_RESET_PFR);  	}  	ice_vsi_realloc_stat_arrays(vsi, prev_txq, prev_rxq); @@ -3759,7 +3762,7 @@ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)  	dev = ice_pf_to_dev(pf);  	if (vsi->tc_cfg.ena_tc == ena_tc &&  	    vsi->mqprio_qopt.mode != TC_MQPRIO_MODE_CHANNEL) -		return ret; +		return 0;  	ice_for_each_traffic_class(i) {  		/* build bitmap of enabled TCs */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 567694bf098b..0d8b8c6f9bd3 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -2316,18 +2316,15 @@ static void ice_service_task(struct work_struct *work)  		}  	} -	if (test_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) { -		/* Plug aux device per request */ -		ice_plug_aux_dev(pf); +	/* unplug aux dev per request, if an unplug request came in +	 * while processing a plug request, this will handle it +	 */ +	if (test_and_clear_bit(ICE_FLAG_UNPLUG_AUX_DEV, pf->flags)) +		ice_unplug_aux_dev(pf); -		/* Mark plugging as done but check whether unplug was -		 * requested during ice_plug_aux_dev() call -		 * (e.g. from ice_clear_rdma_cap()) and if so then -		 * plug aux device. -		 */ -		if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) -			ice_unplug_aux_dev(pf); -	} +	/* Plug aux device per request */ +	if (test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) +		ice_plug_aux_dev(pf);  	if (test_and_clear_bit(ICE_FLAG_MTU_CHANGED, pf->flags)) {  		struct iidc_event *event; @@ -4644,6 +4641,12 @@ static int ice_start_eth(struct ice_vsi *vsi)  	return err;  } +static void ice_stop_eth(struct ice_vsi *vsi) +{ +	ice_fltr_remove_all(vsi); +	ice_vsi_close(vsi); +} +  static int ice_init_eth(struct ice_pf *pf)  {  	struct ice_vsi *vsi = ice_get_main_vsi(pf); @@ -5132,7 +5135,7 @@ void ice_unload(struct ice_pf *pf)  {  	ice_deinit_features(pf);  	ice_deinit_rdma(pf); -	ice_vsi_close(ice_get_main_vsi(pf)); +	ice_stop_eth(ice_get_main_vsi(pf));  	ice_vsi_decfg(ice_get_main_vsi(pf));  	ice_deinit_dev(pf);  } diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index 4eca8d195ef0..b7682de0ae05 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -2788,7 +2788,7 @@ static int  ice_sched_assoc_vsi_to_agg(struct ice_port_info *pi, u32 agg_id,  			   u16 vsi_handle, unsigned long *tc_bitmap)  { -	struct ice_sched_agg_vsi_info *agg_vsi_info, *old_agg_vsi_info = NULL; +	struct ice_sched_agg_vsi_info *agg_vsi_info, *iter, *old_agg_vsi_info = NULL;  	struct ice_sched_agg_info *agg_info, *old_agg_info;  	struct ice_hw *hw = pi->hw;  	int status = 0; @@ -2806,11 +2806,13 @@ ice_sched_assoc_vsi_to_agg(struct ice_port_info *pi, u32 agg_id,  	if (old_agg_info && old_agg_info != agg_info) {  		struct ice_sched_agg_vsi_info *vtmp; -		list_for_each_entry_safe(old_agg_vsi_info, vtmp, +		list_for_each_entry_safe(iter, vtmp,  					 &old_agg_info->agg_vsi_list,  					 list_entry) -			if (old_agg_vsi_info->vsi_handle == vsi_handle) +			if (iter->vsi_handle == vsi_handle) { +				old_agg_vsi_info = iter;  				break; +			}  	}  	/* check if entry already exist */ diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c index 96a64c25e2ef..0cc05e54a781 100644 --- a/drivers/net/ethernet/intel/ice/ice_sriov.c +++ b/drivers/net/ethernet/intel/ice/ice_sriov.c @@ -1341,15 +1341,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)  	struct ice_vf *vf;  	int ret; +	vf = ice_get_vf_by_id(pf, vf_id); +	if (!vf) +		return -EINVAL; +  	if (ice_is_eswitch_mode_switchdev(pf)) {  		dev_info(ice_pf_to_dev(pf), "Trusted VF is forbidden in switchdev mode\n");  		return -EOPNOTSUPP;  	} -	vf = ice_get_vf_by_id(pf, vf_id); -	if (!vf) -		return -EINVAL; -  	ret = ice_check_vf_ready_for_cfg(vf);  	if (ret)  		goto out_put_vf; diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 61f844d22512..46b36851af46 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -1780,18 +1780,36 @@ ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,  int  ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable)  { -	struct ice_vsi_ctx *ctx; +	struct ice_vsi_ctx *ctx, *cached_ctx; +	int status; + +	cached_ctx = ice_get_vsi_ctx(hw, vsi_handle); +	if (!cached_ctx) +		return -ENOENT; -	ctx = ice_get_vsi_ctx(hw, vsi_handle); +	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);  	if (!ctx) -		return -EIO; +		return -ENOMEM; + +	ctx->info.q_opt_rss = cached_ctx->info.q_opt_rss; +	ctx->info.q_opt_tc = cached_ctx->info.q_opt_tc; +	ctx->info.q_opt_flags = cached_ctx->info.q_opt_flags; + +	ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);  	if (enable)  		ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;  	else  		ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; -	return ice_update_vsi(hw, vsi_handle, ctx, NULL); +	status = ice_update_vsi(hw, vsi_handle, ctx, NULL); +	if (!status) { +		cached_ctx->info.q_opt_flags = ctx->info.q_opt_flags; +		cached_ctx->info.valid_sections |= ctx->info.valid_sections; +	} + +	kfree(ctx); +	return status;  }  /** diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c index 6b48cbc049c6..76f29a5bf8d7 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c @@ -1455,8 +1455,8 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,  		if (match.mask->vlan_priority) {  			fltr->flags |= ICE_TC_FLWR_FIELD_VLAN_PRIO;  			headers->vlan_hdr.vlan_prio = -				cpu_to_be16((match.key->vlan_priority << -					     VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK); +				be16_encode_bits(match.key->vlan_priority, +						 VLAN_PRIO_MASK);  		}  		if (match.mask->vlan_tpid) @@ -1489,8 +1489,8 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,  		if (match.mask->vlan_priority) {  			fltr->flags |= ICE_TC_FLWR_FIELD_CVLAN_PRIO;  			headers->cvlan_hdr.vlan_prio = -				cpu_to_be16((match.key->vlan_priority << -					     VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK); +				be16_encode_bits(match.key->vlan_priority, +						 VLAN_PRIO_MASK);  		}  	} diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index dfd22862e926..4fcf2d07eb85 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -938,6 +938,7 @@ ice_reuse_rx_page(struct ice_rx_ring *rx_ring, struct ice_rx_buf *old_buf)   * ice_get_rx_buf - Fetch Rx buffer and synchronize data for use   * @rx_ring: Rx descriptor ring to transact packets on   * @size: size of buffer to add to skb + * @ntc: index of next to clean element   *   * This function will pull an Rx buffer from the ring and synchronize it   * for use by the CPU. @@ -1026,7 +1027,6 @@ ice_build_skb(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp)  /**   * ice_construct_skb - Allocate skb and populate it   * @rx_ring: Rx descriptor ring to transact packets on - * @rx_buf: Rx buffer to pull data from   * @xdp: xdp_buff pointing to the data   *   * This function allocates an skb. It then populates it with the page @@ -1210,6 +1210,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)  				ice_vc_fdir_irq_handler(ctrl_vsi, rx_desc);  			if (++ntc == cnt)  				ntc = 0; +			rx_ring->first_desc = ntc;  			continue;  		} diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c index 7bc5aa340c7d..c8322fb6f2b3 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c @@ -438,6 +438,7 @@ busy:   * ice_finalize_xdp_rx - Bump XDP Tx tail and/or flush redirect map   * @xdp_ring: XDP ring   * @xdp_res: Result of the receive batch + * @first_idx: index to write from caller   *   * This function bumps XDP Tx tail and/or flush redirect map, and   * should be called when a batch of packets has been processed in the diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c index e6ef6b303222..daa6a1e894cf 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c @@ -542,6 +542,87 @@ static void ice_vc_fdir_rem_prof_all(struct ice_vf *vf)  }  /** + * ice_vc_fdir_reset_cnt_all - reset all FDIR counters for this VF FDIR + * @fdir: pointer to the VF FDIR structure + */ +static void ice_vc_fdir_reset_cnt_all(struct ice_vf_fdir *fdir) +{ +	enum ice_fltr_ptype flow; + +	for (flow = ICE_FLTR_PTYPE_NONF_NONE; +	     flow < ICE_FLTR_PTYPE_MAX; flow++) { +		fdir->fdir_fltr_cnt[flow][0] = 0; +		fdir->fdir_fltr_cnt[flow][1] = 0; +	} +} + +/** + * ice_vc_fdir_has_prof_conflict + * @vf: pointer to the VF structure + * @conf: FDIR configuration for each filter + * + * Check if @conf has conflicting profile with existing profiles + * + * Return: true on success, and false on error. + */ +static bool +ice_vc_fdir_has_prof_conflict(struct ice_vf *vf, +			      struct virtchnl_fdir_fltr_conf *conf) +{ +	struct ice_fdir_fltr *desc; + +	list_for_each_entry(desc, &vf->fdir.fdir_rule_list, fltr_node) { +		struct virtchnl_fdir_fltr_conf *existing_conf; +		enum ice_fltr_ptype flow_type_a, flow_type_b; +		struct ice_fdir_fltr *a, *b; + +		existing_conf = to_fltr_conf_from_desc(desc); +		a = &existing_conf->input; +		b = &conf->input; +		flow_type_a = a->flow_type; +		flow_type_b = b->flow_type; + +		/* No need to compare two rules with different tunnel types or +		 * with the same protocol type. +		 */ +		if (existing_conf->ttype != conf->ttype || +		    flow_type_a == flow_type_b) +			continue; + +		switch (flow_type_a) { +		case ICE_FLTR_PTYPE_NONF_IPV4_UDP: +		case ICE_FLTR_PTYPE_NONF_IPV4_TCP: +		case ICE_FLTR_PTYPE_NONF_IPV4_SCTP: +			if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) +				return true; +			break; +		case ICE_FLTR_PTYPE_NONF_IPV4_OTHER: +			if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_UDP || +			    flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_TCP || +			    flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) +				return true; +			break; +		case ICE_FLTR_PTYPE_NONF_IPV6_UDP: +		case ICE_FLTR_PTYPE_NONF_IPV6_TCP: +		case ICE_FLTR_PTYPE_NONF_IPV6_SCTP: +			if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) +				return true; +			break; +		case ICE_FLTR_PTYPE_NONF_IPV6_OTHER: +			if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_UDP || +			    flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_TCP || +			    flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) +				return true; +			break; +		default: +			break; +		} +	} + +	return false; +} + +/**   * ice_vc_fdir_write_flow_prof   * @vf: pointer to the VF structure   * @flow: filter flow type @@ -677,6 +758,13 @@ ice_vc_fdir_config_input_set(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,  	enum ice_fltr_ptype flow;  	int ret; +	ret = ice_vc_fdir_has_prof_conflict(vf, conf); +	if (ret) { +		dev_dbg(dev, "Found flow profile conflict for VF %d\n", +			vf->vf_id); +		return ret; +	} +  	flow = input->flow_type;  	ret = ice_vc_fdir_alloc_prof(vf, flow);  	if (ret) { @@ -1798,7 +1886,7 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)  		v_ret = VIRTCHNL_STATUS_SUCCESS;  		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;  		dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id); -		goto err_free_conf; +		goto err_rem_entry;  	}  	ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun); @@ -1807,15 +1895,16 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)  		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;  		dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",  			vf->vf_id, ret); -		goto err_rem_entry; +		goto err_clr_irq;  	}  exit:  	kfree(stat);  	return ret; -err_rem_entry: +err_clr_irq:  	ice_vc_fdir_clear_irq_ctx(vf); +err_rem_entry:  	ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);  err_free_conf:  	devm_kfree(dev, conf); @@ -1924,6 +2013,7 @@ void ice_vf_fdir_init(struct ice_vf *vf)  	spin_lock_init(&fdir->ctx_lock);  	fdir->ctx_irq.flags = 0;  	fdir->ctx_done.flags = 0; +	ice_vc_fdir_reset_cnt_all(fdir);  }  /** diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index 31565bbafa22..d1e489da7363 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -184,8 +184,6 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx)  	}  	netif_tx_stop_queue(netdev_get_tx_queue(vsi->netdev, q_idx)); -	ice_qvec_dis_irq(vsi, rx_ring, q_vector); -  	ice_fill_txq_meta(vsi, tx_ring, &txq_meta);  	err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, tx_ring, &txq_meta);  	if (err) @@ -200,10 +198,11 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx)  		if (err)  			return err;  	} +	ice_qvec_dis_irq(vsi, rx_ring, q_vector); +  	err = ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, true);  	if (err)  		return err; -	ice_clean_rx_ring(rx_ring);  	ice_qvec_toggle_napi(vsi, q_vector, false);  	ice_qp_clean_rings(vsi, q_idx); diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 03bc1e8af575..274c781b5547 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -109,6 +109,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *);  static void igb_setup_mrqc(struct igb_adapter *);  static int igb_probe(struct pci_dev *, const struct pci_device_id *);  static void igb_remove(struct pci_dev *pdev); +static void igb_init_queue_configuration(struct igb_adapter *adapter);  static int igb_sw_init(struct igb_adapter *);  int igb_open(struct net_device *);  int igb_close(struct net_device *); @@ -175,9 +176,7 @@ static void igb_nfc_filter_restore(struct igb_adapter *adapter);  #ifdef CONFIG_PCI_IOV  static int igb_vf_configure(struct igb_adapter *adapter, int vf); -static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs); -static int igb_disable_sriov(struct pci_dev *dev); -static int igb_pci_disable_sriov(struct pci_dev *dev); +static int igb_disable_sriov(struct pci_dev *dev, bool reinit);  #endif  static int igb_suspend(struct device *); @@ -3665,7 +3664,7 @@ err_sw_init:  	kfree(adapter->shadow_vfta);  	igb_clear_interrupt_scheme(adapter);  #ifdef CONFIG_PCI_IOV -	igb_disable_sriov(pdev); +	igb_disable_sriov(pdev, false);  #endif  	pci_iounmap(pdev, adapter->io_addr);  err_ioremap: @@ -3679,7 +3678,38 @@ err_dma:  }  #ifdef CONFIG_PCI_IOV -static int igb_disable_sriov(struct pci_dev *pdev) +static int igb_sriov_reinit(struct pci_dev *dev) +{ +	struct net_device *netdev = pci_get_drvdata(dev); +	struct igb_adapter *adapter = netdev_priv(netdev); +	struct pci_dev *pdev = adapter->pdev; + +	rtnl_lock(); + +	if (netif_running(netdev)) +		igb_close(netdev); +	else +		igb_reset(adapter); + +	igb_clear_interrupt_scheme(adapter); + +	igb_init_queue_configuration(adapter); + +	if (igb_init_interrupt_scheme(adapter, true)) { +		rtnl_unlock(); +		dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); +		return -ENOMEM; +	} + +	if (netif_running(netdev)) +		igb_open(netdev); + +	rtnl_unlock(); + +	return 0; +} + +static int igb_disable_sriov(struct pci_dev *pdev, bool reinit)  {  	struct net_device *netdev = pci_get_drvdata(pdev);  	struct igb_adapter *adapter = netdev_priv(netdev); @@ -3713,10 +3743,10 @@ static int igb_disable_sriov(struct pci_dev *pdev)  		adapter->flags |= IGB_FLAG_DMAC;  	} -	return 0; +	return reinit ? igb_sriov_reinit(pdev) : 0;  } -static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs) +static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs, bool reinit)  {  	struct net_device *netdev = pci_get_drvdata(pdev);  	struct igb_adapter *adapter = netdev_priv(netdev); @@ -3781,12 +3811,6 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)  			"Unable to allocate memory for VF MAC filter list\n");  	} -	/* only call pci_enable_sriov() if no VFs are allocated already */ -	if (!old_vfs) { -		err = pci_enable_sriov(pdev, adapter->vfs_allocated_count); -		if (err) -			goto err_out; -	}  	dev_info(&pdev->dev, "%d VFs allocated\n",  		 adapter->vfs_allocated_count);  	for (i = 0; i < adapter->vfs_allocated_count; i++) @@ -3794,6 +3818,17 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)  	/* DMA Coalescing is not supported in IOV mode. */  	adapter->flags &= ~IGB_FLAG_DMAC; + +	if (reinit) { +		err = igb_sriov_reinit(pdev); +		if (err) +			goto err_out; +	} + +	/* only call pci_enable_sriov() if no VFs are allocated already */ +	if (!old_vfs) +		err = pci_enable_sriov(pdev, adapter->vfs_allocated_count); +  	goto out;  err_out: @@ -3863,9 +3898,7 @@ static void igb_remove(struct pci_dev *pdev)  	igb_release_hw_control(adapter);  #ifdef CONFIG_PCI_IOV -	rtnl_lock(); -	igb_disable_sriov(pdev); -	rtnl_unlock(); +	igb_disable_sriov(pdev, false);  #endif  	unregister_netdev(netdev); @@ -3911,7 +3944,7 @@ static void igb_probe_vfs(struct igb_adapter *adapter)  	igb_reset_interrupt_capability(adapter);  	pci_sriov_set_totalvfs(pdev, 7); -	igb_enable_sriov(pdev, max_vfs); +	igb_enable_sriov(pdev, max_vfs, false);  #endif /* CONFIG_PCI_IOV */  } @@ -9520,71 +9553,17 @@ static void igb_shutdown(struct pci_dev *pdev)  	}  } -#ifdef CONFIG_PCI_IOV -static int igb_sriov_reinit(struct pci_dev *dev) -{ -	struct net_device *netdev = pci_get_drvdata(dev); -	struct igb_adapter *adapter = netdev_priv(netdev); -	struct pci_dev *pdev = adapter->pdev; - -	rtnl_lock(); - -	if (netif_running(netdev)) -		igb_close(netdev); -	else -		igb_reset(adapter); - -	igb_clear_interrupt_scheme(adapter); - -	igb_init_queue_configuration(adapter); - -	if (igb_init_interrupt_scheme(adapter, true)) { -		rtnl_unlock(); -		dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); -		return -ENOMEM; -	} - -	if (netif_running(netdev)) -		igb_open(netdev); - -	rtnl_unlock(); - -	return 0; -} - -static int igb_pci_disable_sriov(struct pci_dev *dev) -{ -	int err = igb_disable_sriov(dev); - -	if (!err) -		err = igb_sriov_reinit(dev); - -	return err; -} - -static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs) -{ -	int err = igb_enable_sriov(dev, num_vfs); - -	if (err) -		goto out; - -	err = igb_sriov_reinit(dev); -	if (!err) -		return num_vfs; - -out: -	return err; -} - -#endif  static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs)  {  #ifdef CONFIG_PCI_IOV -	if (num_vfs == 0) -		return igb_pci_disable_sriov(dev); -	else -		return igb_pci_enable_sriov(dev, num_vfs); +	int err; + +	if (num_vfs == 0) { +		return igb_disable_sriov(dev, true); +	} else { +		err = igb_enable_sriov(dev, num_vfs, true); +		return err ? err : num_vfs; +	}  #endif  	return 0;  } diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 3a32809510fc..72cb1b56e9f2 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -1074,7 +1074,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)  			  igbvf_intr_msix_rx, 0, adapter->rx_ring->name,  			  netdev);  	if (err) -		goto out; +		goto free_irq_tx;  	adapter->rx_ring->itr_register = E1000_EITR(vector);  	adapter->rx_ring->itr_val = adapter->current_itr; @@ -1083,10 +1083,14 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)  	err = request_irq(adapter->msix_entries[vector].vector,  			  igbvf_msix_other, 0, netdev->name, netdev);  	if (err) -		goto out; +		goto free_irq_rx;  	igbvf_configure_msix(adapter);  	return 0; +free_irq_rx: +	free_irq(adapter->msix_entries[--vector].vector, netdev); +free_irq_tx: +	free_irq(adapter->msix_entries[--vector].vector, netdev);  out:  	return err;  } diff --git a/drivers/net/ethernet/intel/igbvf/vf.c b/drivers/net/ethernet/intel/igbvf/vf.c index b8ba3f94c363..a47a2e3e548c 100644 --- a/drivers/net/ethernet/intel/igbvf/vf.c +++ b/drivers/net/ethernet/intel/igbvf/vf.c @@ -1,6 +1,8 @@  // SPDX-License-Identifier: GPL-2.0  /* Copyright(c) 2009 - 2018 Intel Corporation. */ +#include <linux/etherdevice.h> +  #include "vf.h"  static s32 e1000_check_for_link_vf(struct e1000_hw *hw); @@ -131,11 +133,16 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)  		/* set our "perm_addr" based on info provided by PF */  		ret_val = mbx->ops.read_posted(hw, msgbuf, 3);  		if (!ret_val) { -			if (msgbuf[0] == (E1000_VF_RESET | -					  E1000_VT_MSGTYPE_ACK)) +			switch (msgbuf[0]) { +			case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK:  				memcpy(hw->mac.perm_addr, addr, ETH_ALEN); -			else +				break; +			case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK: +				eth_zero_addr(hw->mac.perm_addr); +				break; +			default:  				ret_val = -E1000_ERR_MAC_INIT; +			}  		}  	} diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 2928a6c73692..25fc6c65209b 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -6010,18 +6010,18 @@ static bool validate_schedule(struct igc_adapter *adapter,  		if (e->command != TC_TAPRIO_CMD_SET_GATES)  			return false; -		for (i = 0; i < adapter->num_tx_queues; i++) { -			if (e->gate_mask & BIT(i)) +		for (i = 0; i < adapter->num_tx_queues; i++) +			if (e->gate_mask & BIT(i)) {  				queue_uses[i]++; -			/* There are limitations: A single queue cannot be -			 * opened and closed multiple times per cycle unless the -			 * gate stays open. Check for it. -			 */ -			if (queue_uses[i] > 1 && -			    !(prev->gate_mask & BIT(i))) -				return false; -		} +				/* There are limitations: A single queue cannot +				 * be opened and closed multiple times per cycle +				 * unless the gate stays open. Check for it. +				 */ +				if (queue_uses[i] > 1 && +				    !(prev->gate_mask & BIT(i))) +					return false; +			}  	}  	return true; |