diff options
Diffstat (limited to 'drivers/net/ethernet/intel/iavf/iavf_main.c')
| -rw-r--r-- | drivers/net/ethernet/intel/iavf/iavf_main.c | 880 | 
1 files changed, 753 insertions, 127 deletions
| diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 847d67e32a54..8125b9120615 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -147,7 +147,7 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw,   *   * Returns 0 on success, negative on failure   **/ -static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs) +int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)  {  	unsigned int wait, delay = 10; @@ -175,6 +175,19 @@ void iavf_schedule_reset(struct iavf_adapter *adapter)  }  /** + * iavf_schedule_request_stats - Set the flags and schedule statistics request + * @adapter: board private structure + * + * Sets IAVF_FLAG_AQ_REQUEST_STATS flag so iavf_watchdog_task() will explicitly + * request and refresh ethtool stats + **/ +void iavf_schedule_request_stats(struct iavf_adapter *adapter) +{ +	adapter->aq_required |= IAVF_FLAG_AQ_REQUEST_STATS; +	mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); +} + +/**   * iavf_tx_timeout - Respond to a Tx Hang   * @netdev: network interface device structure   * @txqueue: queue number that is timing out @@ -450,14 +463,14 @@ iavf_request_traffic_irqs(struct iavf_adapter *adapter, char *basename)  		if (q_vector->tx.ring && q_vector->rx.ring) {  			snprintf(q_vector->name, sizeof(q_vector->name), -				 "iavf-%s-TxRx-%d", basename, rx_int_idx++); +				 "iavf-%s-TxRx-%u", basename, rx_int_idx++);  			tx_int_idx++;  		} else if (q_vector->rx.ring) {  			snprintf(q_vector->name, sizeof(q_vector->name), -				 "iavf-%s-rx-%d", basename, rx_int_idx++); +				 "iavf-%s-rx-%u", basename, rx_int_idx++);  		} else if (q_vector->tx.ring) {  			snprintf(q_vector->name, sizeof(q_vector->name), -				 "iavf-%s-tx-%d", basename, tx_int_idx++); +				 "iavf-%s-tx-%u", basename, tx_int_idx++);  		} else {  			/* skip this unused q_vector */  			continue; @@ -479,10 +492,10 @@ iavf_request_traffic_irqs(struct iavf_adapter *adapter, char *basename)  		irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);  		/* Spread the IRQ affinity hints across online CPUs. Note that  		 * get_cpu_mask returns a mask with a permanent lifetime so -		 * it's safe to use as a hint for irq_set_affinity_hint. +		 * it's safe to use as a hint for irq_update_affinity_hint.  		 */  		cpu = cpumask_local_spread(q_vector->v_idx, -1); -		irq_set_affinity_hint(irq_num, get_cpu_mask(cpu)); +		irq_update_affinity_hint(irq_num, get_cpu_mask(cpu));  	}  	return 0; @@ -492,7 +505,7 @@ free_queue_irqs:  		vector--;  		irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;  		irq_set_affinity_notifier(irq_num, NULL); -		irq_set_affinity_hint(irq_num, NULL); +		irq_update_affinity_hint(irq_num, NULL);  		free_irq(irq_num, &adapter->q_vectors[vector]);  	}  	return err; @@ -544,7 +557,7 @@ static void iavf_free_traffic_irqs(struct iavf_adapter *adapter)  	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); +		irq_update_affinity_hint(irq_num, NULL);  		free_irq(irq_num, &adapter->q_vectors[vector]);  	}  } @@ -633,14 +646,17 @@ static void iavf_configure_rx(struct iavf_adapter *adapter)   * mac_vlan_list_lock.   **/  static struct -iavf_vlan_filter *iavf_find_vlan(struct iavf_adapter *adapter, u16 vlan) +iavf_vlan_filter *iavf_find_vlan(struct iavf_adapter *adapter, +				 struct iavf_vlan vlan)  {  	struct iavf_vlan_filter *f;  	list_for_each_entry(f, &adapter->vlan_filter_list, list) { -		if (vlan == f->vlan) +		if (f->vlan.vid == vlan.vid && +		    f->vlan.tpid == vlan.tpid)  			return f;  	} +  	return NULL;  } @@ -652,7 +668,8 @@ iavf_vlan_filter *iavf_find_vlan(struct iavf_adapter *adapter, u16 vlan)   * Returns ptr to the filter object or NULL when no memory available.   **/  static struct -iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter, u16 vlan) +iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter, +				struct iavf_vlan vlan)  {  	struct iavf_vlan_filter *f = NULL; @@ -681,7 +698,7 @@ clearout:   * @adapter: board private structure   * @vlan: VLAN tag   **/ -static void iavf_del_vlan(struct iavf_adapter *adapter, u16 vlan) +static void iavf_del_vlan(struct iavf_adapter *adapter, struct iavf_vlan vlan)  {  	struct iavf_vlan_filter *f; @@ -697,6 +714,68 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, u16 vlan)  }  /** + * iavf_restore_filters + * @adapter: board private structure + * + * Restore existing non MAC filters when VF netdev comes back up + **/ +static void iavf_restore_filters(struct iavf_adapter *adapter) +{ +	u16 vid; + +	/* 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)); + +	for_each_set_bit(vid, adapter->vsi.active_svlans, VLAN_N_VID) +		iavf_add_vlan(adapter, IAVF_VLAN(vid, ETH_P_8021AD)); +} + +/** + * iavf_get_num_vlans_added - get number of VLANs added + * @adapter: board private structure + */ +static 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); +} + +/** + * iavf_get_max_vlans_allowed - get maximum VLANs allowed for this VF + * @adapter: board private structure + * + * This depends on the negotiated VLAN capability. For VIRTCHNL_VF_OFFLOAD_VLAN, + * do not impose a limit as that maintains current behavior and for + * VIRTCHNL_VF_OFFLOAD_VLAN_V2, use the maximum allowed sent from the PF. + **/ +static u16 iavf_get_max_vlans_allowed(struct iavf_adapter *adapter) +{ +	/* don't impose any limit for VIRTCHNL_VF_OFFLOAD_VLAN since there has +	 * never been a limit on the VF driver side +	 */ +	if (VLAN_ALLOWED(adapter)) +		return VLAN_N_VID; +	else if (VLAN_V2_ALLOWED(adapter)) +		return adapter->vlan_v2_caps.filtering.max_filters; + +	return 0; +} + +/** + * iavf_max_vlans_added - check if maximum VLANs allowed already exist + * @adapter: board private structure + **/ +static bool iavf_max_vlans_added(struct iavf_adapter *adapter) +{ +	if (iavf_get_num_vlans_added(adapter) < +	    iavf_get_max_vlans_allowed(adapter)) +		return false; + +	return true; +} + +/**   * iavf_vlan_rx_add_vid - Add a VLAN filter to a device   * @netdev: network device struct   * @proto: unused protocol data @@ -707,10 +786,23 @@ static int iavf_vlan_rx_add_vid(struct net_device *netdev,  {  	struct iavf_adapter *adapter = netdev_priv(netdev); -	if (!VLAN_ALLOWED(adapter)) +	if (!VLAN_FILTERING_ALLOWED(adapter)) +		return -EIO; + +	if (iavf_max_vlans_added(adapter)) { +		netdev_err(netdev, "Max allowed VLAN filters %u. Remove existing VLANs or disable filtering via Ethtool if supported.\n", +			   iavf_get_max_vlans_allowed(adapter));  		return -EIO; -	if (iavf_add_vlan(adapter, vid) == NULL) +	} + +	if (!iavf_add_vlan(adapter, IAVF_VLAN(vid, be16_to_cpu(proto))))  		return -ENOMEM; + +	if (proto == cpu_to_be16(ETH_P_8021Q)) +		set_bit(vid, adapter->vsi.active_cvlans); +	else +		set_bit(vid, adapter->vsi.active_svlans); +  	return 0;  } @@ -725,11 +817,13 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev,  {  	struct iavf_adapter *adapter = netdev_priv(netdev); -	if (VLAN_ALLOWED(adapter)) { -		iavf_del_vlan(adapter, vid); -		return 0; -	} -	return -EIO; +	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); + +	return 0;  }  /** @@ -1122,6 +1216,86 @@ static void iavf_free_queues(struct iavf_adapter *adapter)  }  /** + * iavf_set_queue_vlan_tag_loc - set location for VLAN tag offload + * @adapter: board private structure + * + * Based on negotiated capabilities, the VLAN tag needs to be inserted and/or + * stripped in certain descriptor fields. Instead of checking the offload + * capability bits in the hot path, cache the location the ring specific + * flags. + */ +void iavf_set_queue_vlan_tag_loc(struct iavf_adapter *adapter) +{ +	int i; + +	for (i = 0; i < adapter->num_active_queues; i++) { +		struct iavf_ring *tx_ring = &adapter->tx_rings[i]; +		struct iavf_ring *rx_ring = &adapter->rx_rings[i]; + +		/* prevent multiple L2TAG bits being set after VFR */ +		tx_ring->flags &= +			~(IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 | +			  IAVF_TXR_FLAGS_VLAN_TAG_LOC_L2TAG2); +		rx_ring->flags &= +			~(IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 | +			  IAVF_RXR_FLAGS_VLAN_TAG_LOC_L2TAG2_2); + +		if (VLAN_ALLOWED(adapter)) { +			tx_ring->flags |= IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1; +			rx_ring->flags |= IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1; +		} else if (VLAN_V2_ALLOWED(adapter)) { +			struct virtchnl_vlan_supported_caps *stripping_support; +			struct virtchnl_vlan_supported_caps *insertion_support; + +			stripping_support = +				&adapter->vlan_v2_caps.offloads.stripping_support; +			insertion_support = +				&adapter->vlan_v2_caps.offloads.insertion_support; + +			if (stripping_support->outer) { +				if (stripping_support->outer & +				    VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1) +					rx_ring->flags |= +						IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1; +				else if (stripping_support->outer & +					 VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2) +					rx_ring->flags |= +						IAVF_RXR_FLAGS_VLAN_TAG_LOC_L2TAG2_2; +			} else if (stripping_support->inner) { +				if (stripping_support->inner & +				    VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1) +					rx_ring->flags |= +						IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1; +				else if (stripping_support->inner & +					 VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2) +					rx_ring->flags |= +						IAVF_RXR_FLAGS_VLAN_TAG_LOC_L2TAG2_2; +			} + +			if (insertion_support->outer) { +				if (insertion_support->outer & +				    VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1) +					tx_ring->flags |= +						IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1; +				else if (insertion_support->outer & +					 VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2) +					tx_ring->flags |= +						IAVF_TXR_FLAGS_VLAN_TAG_LOC_L2TAG2; +			} else if (insertion_support->inner) { +				if (insertion_support->inner & +				    VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1) +					tx_ring->flags |= +						IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1; +				else if (insertion_support->inner & +					 VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2) +					tx_ring->flags |= +						IAVF_TXR_FLAGS_VLAN_TAG_LOC_L2TAG2; +			} +		} +	} +} + +/**   * iavf_alloc_queues - Allocate memory for all rings   * @adapter: board private structure to initialize   * @@ -1182,6 +1356,8 @@ static int iavf_alloc_queues(struct iavf_adapter *adapter)  	adapter->num_active_queues = num_active_queues; +	iavf_set_queue_vlan_tag_loc(adapter); +  	return 0;  err_out: @@ -1554,6 +1730,8 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)  {  	if (adapter->aq_required & IAVF_FLAG_AQ_GET_CONFIG)  		return iavf_send_vf_config_msg(adapter); +	if (adapter->aq_required & IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS) +		return iavf_send_vf_offload_vlan_v2_msg(adapter);  	if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_QUEUES) {  		iavf_disable_queues(adapter);  		return 0; @@ -1639,8 +1817,7 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)  		iavf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC);  		return 0;  	} - -	if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) && +	if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) ||  	    (adapter->aq_required & IAVF_FLAG_AQ_RELEASE_ALLMULTI)) {  		iavf_set_promiscuous(adapter, 0);  		return 0; @@ -1688,10 +1865,133 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)  		iavf_del_adv_rss_cfg(adapter);  		return 0;  	} +	if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_STRIPPING) { +		iavf_disable_vlan_stripping_v2(adapter, ETH_P_8021Q); +		return 0; +	} +	if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_STAG_VLAN_STRIPPING) { +		iavf_disable_vlan_stripping_v2(adapter, ETH_P_8021AD); +		return 0; +	} +	if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_STRIPPING) { +		iavf_enable_vlan_stripping_v2(adapter, ETH_P_8021Q); +		return 0; +	} +	if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_STAG_VLAN_STRIPPING) { +		iavf_enable_vlan_stripping_v2(adapter, ETH_P_8021AD); +		return 0; +	} +	if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_INSERTION) { +		iavf_disable_vlan_insertion_v2(adapter, ETH_P_8021Q); +		return 0; +	} +	if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_STAG_VLAN_INSERTION) { +		iavf_disable_vlan_insertion_v2(adapter, ETH_P_8021AD); +		return 0; +	} +	if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_INSERTION) { +		iavf_enable_vlan_insertion_v2(adapter, ETH_P_8021Q); +		return 0; +	} +	if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_STAG_VLAN_INSERTION) { +		iavf_enable_vlan_insertion_v2(adapter, ETH_P_8021AD); +		return 0; +	} + +	if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_STATS) { +		iavf_request_stats(adapter); +		return 0; +	} +  	return -EAGAIN;  }  /** + * iavf_set_vlan_offload_features - set VLAN offload configuration + * @adapter: board private structure + * @prev_features: previous features used for comparison + * @features: updated features used for configuration + * + * Set the aq_required bit(s) based on the requested features passed in to + * configure VLAN stripping and/or VLAN insertion if supported. Also, schedule + * the watchdog if any changes are requested to expedite the request via + * virtchnl. + **/ +void +iavf_set_vlan_offload_features(struct iavf_adapter *adapter, +			       netdev_features_t prev_features, +			       netdev_features_t features) +{ +	bool enable_stripping = true, enable_insertion = true; +	u16 vlan_ethertype = 0; +	u64 aq_required = 0; + +	/* keep cases separate because one ethertype for offloads can be +	 * disabled at the same time as another is disabled, so check for an +	 * enabled ethertype first, then check for disabled. Default to +	 * ETH_P_8021Q so an ethertype is specified if disabling insertion and +	 * stripping. +	 */ +	if (features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX)) +		vlan_ethertype = ETH_P_8021AD; +	else if (features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX)) +		vlan_ethertype = ETH_P_8021Q; +	else if (prev_features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX)) +		vlan_ethertype = ETH_P_8021AD; +	else if (prev_features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX)) +		vlan_ethertype = ETH_P_8021Q; +	else +		vlan_ethertype = ETH_P_8021Q; + +	if (!(features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_CTAG_RX))) +		enable_stripping = false; +	if (!(features & (NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_VLAN_CTAG_TX))) +		enable_insertion = false; + +	if (VLAN_ALLOWED(adapter)) { +		/* VIRTCHNL_VF_OFFLOAD_VLAN only has support for toggling VLAN +		 * stripping via virtchnl. VLAN insertion can be toggled on the +		 * netdev, but it doesn't require a virtchnl message +		 */ +		if (enable_stripping) +			aq_required |= IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING; +		else +			aq_required |= IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING; + +	} else if (VLAN_V2_ALLOWED(adapter)) { +		switch (vlan_ethertype) { +		case ETH_P_8021Q: +			if (enable_stripping) +				aq_required |= IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_STRIPPING; +			else +				aq_required |= IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_STRIPPING; + +			if (enable_insertion) +				aq_required |= IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_INSERTION; +			else +				aq_required |= IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_INSERTION; +			break; +		case ETH_P_8021AD: +			if (enable_stripping) +				aq_required |= IAVF_FLAG_AQ_ENABLE_STAG_VLAN_STRIPPING; +			else +				aq_required |= IAVF_FLAG_AQ_DISABLE_STAG_VLAN_STRIPPING; + +			if (enable_insertion) +				aq_required |= IAVF_FLAG_AQ_ENABLE_STAG_VLAN_INSERTION; +			else +				aq_required |= IAVF_FLAG_AQ_DISABLE_STAG_VLAN_INSERTION; +			break; +		} +	} + +	if (aq_required) { +		adapter->aq_required |= aq_required; +		mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); +	} +} + +/**   * iavf_startup - first step of driver startup   * @adapter: board private structure   * @@ -1793,6 +2093,59 @@ err:  }  /** + * iavf_parse_vf_resource_msg - parse response from VIRTCHNL_OP_GET_VF_RESOURCES + * @adapter: board private structure + */ +int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter) +{ +	int i, num_req_queues = adapter->num_req_queues; +	struct iavf_vsi *vsi = &adapter->vsi; + +	for (i = 0; i < adapter->vf_res->num_vsis; i++) { +		if (adapter->vf_res->vsi_res[i].vsi_type == VIRTCHNL_VSI_SRIOV) +			adapter->vsi_res = &adapter->vf_res->vsi_res[i]; +	} +	if (!adapter->vsi_res) { +		dev_err(&adapter->pdev->dev, "No LAN VSI found\n"); +		return -ENODEV; +	} + +	if (num_req_queues && +	    num_req_queues > adapter->vsi_res->num_queue_pairs) { +		/* Problem.  The PF gave us fewer queues than what we had +		 * negotiated in our request.  Need a reset to see if we can't +		 * get back to a working state. +		 */ +		dev_err(&adapter->pdev->dev, +			"Requested %d queues, but PF only gave us %d.\n", +			num_req_queues, +			adapter->vsi_res->num_queue_pairs); +		adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED; +		adapter->num_req_queues = adapter->vsi_res->num_queue_pairs; +		iavf_schedule_reset(adapter); + +		return -EAGAIN; +	} +	adapter->num_req_queues = 0; +	adapter->vsi.id = adapter->vsi_res->vsi_id; + +	adapter->vsi.back = adapter; +	adapter->vsi.base_vector = 1; +	adapter->vsi.work_limit = IAVF_DEFAULT_IRQ_WORK; +	vsi->netdev = adapter->netdev; +	vsi->qs_handle = adapter->vsi_res->qset_handle; +	if (adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) { +		adapter->rss_key_size = adapter->vf_res->rss_key_size; +		adapter->rss_lut_size = adapter->vf_res->rss_lut_size; +	} else { +		adapter->rss_key_size = IAVF_HKEY_ARRAY_SIZE; +		adapter->rss_lut_size = IAVF_HLUT_ARRAY_SIZE; +	} + +	return 0; +} + +/**   * iavf_init_get_resources - third step of driver startup   * @adapter: board private structure   * @@ -1803,7 +2156,6 @@ err:   **/  static void iavf_init_get_resources(struct iavf_adapter *adapter)  { -	struct net_device *netdev = adapter->netdev;  	struct pci_dev *pdev = adapter->pdev;  	struct iavf_hw *hw = &adapter->hw;  	int err; @@ -1821,7 +2173,7 @@ static void iavf_init_get_resources(struct iavf_adapter *adapter)  	err = iavf_get_vf_config(adapter);  	if (err == IAVF_ERR_ADMIN_QUEUE_NO_WORK) {  		err = iavf_send_vf_config_msg(adapter); -		goto err; +		goto err_alloc;  	} else if (err == IAVF_ERR_PARAM) {  		/* We only get ERR_PARAM if the device is in a very bad  		 * state or if we've been disabled for previous bad @@ -1836,9 +2188,83 @@ static void iavf_init_get_resources(struct iavf_adapter *adapter)  		goto err_alloc;  	} -	err = iavf_process_config(adapter); +	err = iavf_parse_vf_resource_msg(adapter);  	if (err)  		goto err_alloc; + +	err = iavf_send_vf_offload_vlan_v2_msg(adapter); +	if (err == -EOPNOTSUPP) { +		/* underlying PF doesn't support VIRTCHNL_VF_OFFLOAD_VLAN_V2, so +		 * go directly to finishing initialization +		 */ +		iavf_change_state(adapter, __IAVF_INIT_CONFIG_ADAPTER); +		return; +	} else if (err) { +		dev_err(&pdev->dev, "Unable to send offload vlan v2 request (%d)\n", +			err); +		goto err_alloc; +	} + +	/* underlying PF supports VIRTCHNL_VF_OFFLOAD_VLAN_V2, so update the +	 * state accordingly +	 */ +	iavf_change_state(adapter, __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS); +	return; + +err_alloc: +	kfree(adapter->vf_res); +	adapter->vf_res = NULL; +err: +	iavf_change_state(adapter, __IAVF_INIT_FAILED); +} + +/** + * iavf_init_get_offload_vlan_v2_caps - part of driver startup + * @adapter: board private structure + * + * Function processes __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS driver state if the + * VF negotiates VIRTCHNL_VF_OFFLOAD_VLAN_V2. If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is + * not negotiated, then this state will never be entered. + **/ +static void iavf_init_get_offload_vlan_v2_caps(struct iavf_adapter *adapter) +{ +	int ret; + +	WARN_ON(adapter->state != __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS); + +	memset(&adapter->vlan_v2_caps, 0, sizeof(adapter->vlan_v2_caps)); + +	ret = iavf_get_vf_vlan_v2_caps(adapter); +	if (ret) { +		if (ret == IAVF_ERR_ADMIN_QUEUE_NO_WORK) +			iavf_send_vf_offload_vlan_v2_msg(adapter); +		goto err; +	} + +	iavf_change_state(adapter, __IAVF_INIT_CONFIG_ADAPTER); +	return; +err: +	iavf_change_state(adapter, __IAVF_INIT_FAILED); +} + +/** + * iavf_init_config_adapter - last part of driver startup + * @adapter: board private structure + * + * After all the supported capabilities are negotiated, then the + * __IAVF_INIT_CONFIG_ADAPTER state will finish driver initialization. + */ +static void iavf_init_config_adapter(struct iavf_adapter *adapter) +{ +	struct net_device *netdev = adapter->netdev; +	struct pci_dev *pdev = adapter->pdev; +	int err; + +	WARN_ON(adapter->state != __IAVF_INIT_CONFIG_ADAPTER); + +	if (iavf_process_config(adapter)) +		goto err; +  	adapter->current_op = VIRTCHNL_OP_UNKNOWN;  	adapter->flags |= IAVF_FLAG_RX_CSUM_ENABLED; @@ -1921,6 +2347,10 @@ static void iavf_init_get_resources(struct iavf_adapter *adapter)  	else  		iavf_init_rss(adapter); +	if (VLAN_V2_ALLOWED(adapter)) +		/* request initial VLAN offload settings */ +		iavf_set_vlan_offload_features(adapter, 0, netdev->features); +  	return;  err_mem:  	iavf_free_rss(adapter); @@ -1928,9 +2358,6 @@ err_register:  	iavf_free_misc_irq(adapter);  err_sw_init:  	iavf_reset_interrupt_capability(adapter); -err_alloc: -	kfree(adapter->vf_res); -	adapter->vf_res = NULL;  err:  	iavf_change_state(adapter, __IAVF_INIT_FAILED);  } @@ -1979,6 +2406,18 @@ static void iavf_watchdog_task(struct work_struct *work)  		queue_delayed_work(iavf_wq, &adapter->watchdog_task,  				   msecs_to_jiffies(1));  		return; +	case __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS: +		iavf_init_get_offload_vlan_v2_caps(adapter); +		mutex_unlock(&adapter->crit_lock); +		queue_delayed_work(iavf_wq, &adapter->watchdog_task, +				   msecs_to_jiffies(1)); +		return; +	case __IAVF_INIT_CONFIG_ADAPTER: +		iavf_init_config_adapter(adapter); +		mutex_unlock(&adapter->crit_lock); +		queue_delayed_work(iavf_wq, &adapter->watchdog_task, +				   msecs_to_jiffies(1)); +		return;  	case __IAVF_INIT_FAILED:  		if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) {  			dev_err(&adapter->pdev->dev, @@ -2012,6 +2451,7 @@ static void iavf_watchdog_task(struct work_struct *work)  		}  		adapter->aq_required = 0;  		adapter->current_op = VIRTCHNL_OP_UNKNOWN; +		mutex_unlock(&adapter->crit_lock);  		queue_delayed_work(iavf_wq,  				   &adapter->watchdog_task,  				   msecs_to_jiffies(10)); @@ -2031,10 +2471,13 @@ static void iavf_watchdog_task(struct work_struct *work)  				iavf_send_api_ver(adapter);  			}  		} else { +			int ret = iavf_process_aq_command(adapter); +  			/* An error will be returned if no commands were  			 * processed; use this opportunity to update stats +			 * if the error isn't -ENOTSUPP  			 */ -			if (iavf_process_aq_command(adapter) && +			if (ret && ret != -EOPNOTSUPP &&  			    adapter->state == __IAVF_RUNNING)  				iavf_request_stats(adapter);  		} @@ -2042,16 +2485,14 @@ static void iavf_watchdog_task(struct work_struct *work)  			iavf_detect_recover_hung(&adapter->vsi);  		break;  	case __IAVF_REMOVE: -		mutex_unlock(&adapter->crit_lock); -		return;  	default: +		mutex_unlock(&adapter->crit_lock);  		return;  	}  	/* check for hw reset */  	reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;  	if (!reg_val) { -		iavf_change_state(adapter, __IAVF_RESETTING);  		adapter->flags |= IAVF_FLAG_RESET_PENDING;  		adapter->aq_required = 0;  		adapter->current_op = VIRTCHNL_OP_UNKNOWN; @@ -2123,8 +2564,8 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)  	iavf_free_misc_irq(adapter);  	iavf_reset_interrupt_capability(adapter); -	iavf_free_queues(adapter);  	iavf_free_q_vectors(adapter); +	iavf_free_queues(adapter);  	memset(adapter->vf_res, 0, IAVF_VIRTCHNL_VF_RESOURCE_SIZE);  	iavf_shutdown_adminq(&adapter->hw);  	adapter->netdev->flags &= ~IFF_UP; @@ -2152,7 +2593,6 @@ static void iavf_reset_task(struct work_struct *work)  	struct net_device *netdev = adapter->netdev;  	struct iavf_hw *hw = &adapter->hw;  	struct iavf_mac_filter *f, *ftmp; -	struct iavf_vlan_filter *vlf;  	struct iavf_cloud_filter *cf;  	u32 reg_val;  	int i = 0, err; @@ -2215,6 +2655,7 @@ static void iavf_reset_task(struct work_struct *work)  	}  	pci_set_master(adapter->pdev); +	pci_restore_msi_state(adapter->pdev);  	if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) {  		dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", @@ -2233,6 +2674,7 @@ continue_reset:  		   (adapter->state == __IAVF_RESETTING));  	if (running) { +		netdev->flags &= ~IFF_UP;  		netif_carrier_off(netdev);  		netif_tx_stop_all_queues(netdev);  		adapter->link_up = false; @@ -2274,6 +2716,13 @@ continue_reset:  	}  	adapter->aq_required |= IAVF_FLAG_AQ_GET_CONFIG; +	/* always set since VIRTCHNL_OP_GET_VF_RESOURCES has not been +	 * sent/received yet, so VLAN_V2_ALLOWED() cannot is not reliable here, +	 * however the VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS won't be sent until +	 * VIRTCHNL_OP_GET_VF_RESOURCES and VIRTCHNL_VF_OFFLOAD_VLAN_V2 have +	 * been successfully sent and negotiated +	 */ +	adapter->aq_required |= IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS;  	adapter->aq_required |= IAVF_FLAG_AQ_MAP_VECTORS;  	spin_lock_bh(&adapter->mac_vlan_list_lock); @@ -2292,11 +2741,6 @@ continue_reset:  	list_for_each_entry(f, &adapter->mac_filter_list, list) {  		f->add = true;  	} -	/* re-add all VLAN filters */ -	list_for_each_entry(vlf, &adapter->vlan_filter_list, list) { -		vlf->add = true; -	} -  	spin_unlock_bh(&adapter->mac_vlan_list_lock);  	/* check if TCs are running and re-add all cloud filters */ @@ -2310,7 +2754,6 @@ continue_reset:  	spin_unlock_bh(&adapter->cloud_filter_list_lock);  	adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER; -	adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;  	adapter->aq_required |= IAVF_FLAG_AQ_ADD_CLOUD_FILTER;  	iavf_misc_irq_enable(adapter); @@ -2344,7 +2787,7 @@ continue_reset:  		 * to __IAVF_RUNNING  		 */  		iavf_up_complete(adapter); - +		netdev->flags |= IFF_UP;  		iavf_irq_enable(adapter, true);  	} else {  		iavf_change_state(adapter, __IAVF_DOWN); @@ -2357,8 +2800,10 @@ continue_reset:  reset_err:  	mutex_unlock(&adapter->client_lock);  	mutex_unlock(&adapter->crit_lock); -	if (running) +	if (running) {  		iavf_change_state(adapter, __IAVF_RUNNING); +		netdev->flags |= IFF_UP; +	}  	dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");  	iavf_close(netdev);  } @@ -2410,7 +2855,7 @@ static void iavf_adminq_task(struct work_struct *work)  	/* check for error indications */  	val = rd32(hw, hw->aq.arq.len); -	if (val == 0xdeadbeef) /* indicates device in reset */ +	if (val == 0xdeadbeef || val == 0xffffffff) /* device in reset */  		goto freedom;  	oldval = val;  	if (val & IAVF_VF_ARQLEN1_ARQVFE_MASK) { @@ -2678,8 +3123,11 @@ static int iavf_validate_ch_config(struct iavf_adapter *adapter,  		total_max_rate += tx_rate;  		num_qps += mqprio_qopt->qopt.count[i];  	} -	if (num_qps > IAVF_MAX_REQ_QUEUES) +	if (num_qps > adapter->num_active_queues) { +		dev_err(&adapter->pdev->dev, +			"Cannot support requested number of queues\n");  		return -EINVAL; +	}  	ret = iavf_validate_tx_bandwidth(adapter, total_max_rate);  	return ret; @@ -2880,7 +3328,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,  			} else {  				dev_err(&adapter->pdev->dev, "Bad ether dest mask %pM\n",  					match.mask->dst); -				return IAVF_ERR_CONFIG; +				return -EINVAL;  			}  		} @@ -2890,7 +3338,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,  			} else {  				dev_err(&adapter->pdev->dev, "Bad ether src mask %pM\n",  					match.mask->src); -				return IAVF_ERR_CONFIG; +				return -EINVAL;  			}  		} @@ -2925,7 +3373,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,  			} else {  				dev_err(&adapter->pdev->dev, "Bad vlan mask %u\n",  					match.mask->vlan_id); -				return IAVF_ERR_CONFIG; +				return -EINVAL;  			}  		}  		vf->mask.tcp_spec.vlan_id |= cpu_to_be16(0xffff); @@ -2949,7 +3397,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,  			} else {  				dev_err(&adapter->pdev->dev, "Bad ip dst mask 0x%08x\n",  					be32_to_cpu(match.mask->dst)); -				return IAVF_ERR_CONFIG; +				return -EINVAL;  			}  		} @@ -2959,13 +3407,13 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,  			} else {  				dev_err(&adapter->pdev->dev, "Bad ip src mask 0x%08x\n",  					be32_to_cpu(match.mask->dst)); -				return IAVF_ERR_CONFIG; +				return -EINVAL;  			}  		}  		if (field_flags & IAVF_CLOUD_FIELD_TEN_ID) {  			dev_info(&adapter->pdev->dev, "Tenant id not allowed for ip filter\n"); -			return IAVF_ERR_CONFIG; +			return -EINVAL;  		}  		if (match.key->dst) {  			vf->mask.tcp_spec.dst_ip[0] |= cpu_to_be32(0xffffffff); @@ -2986,7 +3434,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,  		if (ipv6_addr_any(&match.mask->dst)) {  			dev_err(&adapter->pdev->dev, "Bad ipv6 dst mask 0x%02x\n",  				IPV6_ADDR_ANY); -			return IAVF_ERR_CONFIG; +			return -EINVAL;  		}  		/* src and dest IPv6 address should not be LOOPBACK @@ -2996,7 +3444,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,  		    ipv6_addr_loopback(&match.key->src)) {  			dev_err(&adapter->pdev->dev,  				"ipv6 addr should not be loopback\n"); -			return IAVF_ERR_CONFIG; +			return -EINVAL;  		}  		if (!ipv6_addr_any(&match.mask->dst) ||  		    !ipv6_addr_any(&match.mask->src)) @@ -3021,7 +3469,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,  			} else {  				dev_err(&adapter->pdev->dev, "Bad src port mask %u\n",  					be16_to_cpu(match.mask->src)); -				return IAVF_ERR_CONFIG; +				return -EINVAL;  			}  		} @@ -3031,7 +3479,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,  			} else {  				dev_err(&adapter->pdev->dev, "Bad dst port mask %u\n",  					be16_to_cpu(match.mask->dst)); -				return IAVF_ERR_CONFIG; +				return -EINVAL;  			}  		}  		if (match.key->dst) { @@ -3095,8 +3543,10 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter,  		return -ENOMEM;  	while (!mutex_trylock(&adapter->crit_lock)) { -		if (--count == 0) -			goto err; +		if (--count == 0) { +			kfree(filter); +			return err; +		}  		udelay(1);  	} @@ -3107,11 +3557,11 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter,  	/* start out with flow type and eth type IPv4 to begin with */  	filter->f.flow_type = VIRTCHNL_TCP_V4_FLOW;  	err = iavf_parse_cls_flower(adapter, cls_flower, filter); -	if (err < 0) +	if (err)  		goto err;  	err = iavf_handle_tclass(adapter, tc, filter); -	if (err < 0) +	if (err)  		goto err;  	/* add filter to the list */ @@ -3308,6 +3758,9 @@ static int iavf_open(struct net_device *netdev)  	spin_unlock_bh(&adapter->mac_vlan_list_lock); +	/* Restore VLAN filters that were removed with IFF_DOWN */ +	iavf_restore_filters(adapter); +  	iavf_configure(adapter);  	iavf_up_complete(adapter); @@ -3393,6 +3846,8 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)  {  	struct iavf_adapter *adapter = netdev_priv(netdev); +	netdev_dbg(netdev, "changing MTU from %d to %d\n", +		   netdev->mtu, new_mtu);  	netdev->mtu = new_mtu;  	if (CLIENT_ENABLED(adapter)) {  		iavf_notify_client_l2_params(&adapter->vsi); @@ -3404,6 +3859,11 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)  	return 0;  } +#define NETIF_VLAN_OFFLOAD_FEATURES	(NETIF_F_HW_VLAN_CTAG_RX | \ +					 NETIF_F_HW_VLAN_CTAG_TX | \ +					 NETIF_F_HW_VLAN_STAG_RX | \ +					 NETIF_F_HW_VLAN_STAG_TX) +  /**   * iavf_set_features - set the netdev feature flags   * @netdev: ptr to the netdev being adjusted @@ -3415,20 +3875,11 @@ static int iavf_set_features(struct net_device *netdev,  {  	struct iavf_adapter *adapter = netdev_priv(netdev); -	/* Don't allow changing VLAN_RX flag when adapter is not capable -	 * of VLAN offload -	 */ -	if (!VLAN_ALLOWED(adapter)) { -		if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX) -			return -EINVAL; -	} else if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX) { -		if (features & NETIF_F_HW_VLAN_CTAG_RX) -			adapter->aq_required |= -				IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING; -		else -			adapter->aq_required |= -				IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING; -	} +	/* trigger update on any VLAN feature change */ +	if ((netdev->features & NETIF_VLAN_OFFLOAD_FEATURES) ^ +	    (features & NETIF_VLAN_OFFLOAD_FEATURES)) +		iavf_set_vlan_offload_features(adapter, netdev->features, +					       features);  	return 0;  } @@ -3492,6 +3943,228 @@ out_err:  }  /** + * iavf_get_netdev_vlan_hw_features - get NETDEV VLAN features that can toggle on/off + * @adapter: board private structure + * + * Depending on whether VIRTHCNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 + * were negotiated determine the VLAN features that can be toggled on and off. + **/ +static netdev_features_t +iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter) +{ +	netdev_features_t hw_features = 0; + +	if (!adapter->vf_res || !adapter->vf_res->vf_cap_flags) +		return hw_features; + +	/* Enable VLAN features if supported */ +	if (VLAN_ALLOWED(adapter)) { +		hw_features |= (NETIF_F_HW_VLAN_CTAG_TX | +				NETIF_F_HW_VLAN_CTAG_RX); +	} else if (VLAN_V2_ALLOWED(adapter)) { +		struct virtchnl_vlan_caps *vlan_v2_caps = +			&adapter->vlan_v2_caps; +		struct virtchnl_vlan_supported_caps *stripping_support = +			&vlan_v2_caps->offloads.stripping_support; +		struct virtchnl_vlan_supported_caps *insertion_support = +			&vlan_v2_caps->offloads.insertion_support; + +		if (stripping_support->outer != VIRTCHNL_VLAN_UNSUPPORTED && +		    stripping_support->outer & VIRTCHNL_VLAN_TOGGLE) { +			if (stripping_support->outer & +			    VIRTCHNL_VLAN_ETHERTYPE_8100) +				hw_features |= NETIF_F_HW_VLAN_CTAG_RX; +			if (stripping_support->outer & +			    VIRTCHNL_VLAN_ETHERTYPE_88A8) +				hw_features |= NETIF_F_HW_VLAN_STAG_RX; +		} else if (stripping_support->inner != +			   VIRTCHNL_VLAN_UNSUPPORTED && +			   stripping_support->inner & VIRTCHNL_VLAN_TOGGLE) { +			if (stripping_support->inner & +			    VIRTCHNL_VLAN_ETHERTYPE_8100) +				hw_features |= NETIF_F_HW_VLAN_CTAG_RX; +		} + +		if (insertion_support->outer != VIRTCHNL_VLAN_UNSUPPORTED && +		    insertion_support->outer & VIRTCHNL_VLAN_TOGGLE) { +			if (insertion_support->outer & +			    VIRTCHNL_VLAN_ETHERTYPE_8100) +				hw_features |= NETIF_F_HW_VLAN_CTAG_TX; +			if (insertion_support->outer & +			    VIRTCHNL_VLAN_ETHERTYPE_88A8) +				hw_features |= NETIF_F_HW_VLAN_STAG_TX; +		} else if (insertion_support->inner && +			   insertion_support->inner & VIRTCHNL_VLAN_TOGGLE) { +			if (insertion_support->inner & +			    VIRTCHNL_VLAN_ETHERTYPE_8100) +				hw_features |= NETIF_F_HW_VLAN_CTAG_TX; +		} +	} + +	return hw_features; +} + +/** + * iavf_get_netdev_vlan_features - get the enabled NETDEV VLAN fetures + * @adapter: board private structure + * + * Depending on whether VIRTHCNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 + * were negotiated determine the VLAN features that are enabled by default. + **/ +static netdev_features_t +iavf_get_netdev_vlan_features(struct iavf_adapter *adapter) +{ +	netdev_features_t features = 0; + +	if (!adapter->vf_res || !adapter->vf_res->vf_cap_flags) +		return features; + +	if (VLAN_ALLOWED(adapter)) { +		features |= NETIF_F_HW_VLAN_CTAG_FILTER | +			NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX; +	} else if (VLAN_V2_ALLOWED(adapter)) { +		struct virtchnl_vlan_caps *vlan_v2_caps = +			&adapter->vlan_v2_caps; +		struct virtchnl_vlan_supported_caps *filtering_support = +			&vlan_v2_caps->filtering.filtering_support; +		struct virtchnl_vlan_supported_caps *stripping_support = +			&vlan_v2_caps->offloads.stripping_support; +		struct virtchnl_vlan_supported_caps *insertion_support = +			&vlan_v2_caps->offloads.insertion_support; +		u32 ethertype_init; + +		/* give priority to outer stripping and don't support both outer +		 * and inner stripping +		 */ +		ethertype_init = vlan_v2_caps->offloads.ethertype_init; +		if (stripping_support->outer != VIRTCHNL_VLAN_UNSUPPORTED) { +			if (stripping_support->outer & +			    VIRTCHNL_VLAN_ETHERTYPE_8100 && +			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100) +				features |= NETIF_F_HW_VLAN_CTAG_RX; +			else if (stripping_support->outer & +				 VIRTCHNL_VLAN_ETHERTYPE_88A8 && +				 ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8) +				features |= NETIF_F_HW_VLAN_STAG_RX; +		} else if (stripping_support->inner != +			   VIRTCHNL_VLAN_UNSUPPORTED) { +			if (stripping_support->inner & +			    VIRTCHNL_VLAN_ETHERTYPE_8100 && +			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100) +				features |= NETIF_F_HW_VLAN_CTAG_RX; +		} + +		/* give priority to outer insertion and don't support both outer +		 * and inner insertion +		 */ +		if (insertion_support->outer != VIRTCHNL_VLAN_UNSUPPORTED) { +			if (insertion_support->outer & +			    VIRTCHNL_VLAN_ETHERTYPE_8100 && +			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100) +				features |= NETIF_F_HW_VLAN_CTAG_TX; +			else if (insertion_support->outer & +				 VIRTCHNL_VLAN_ETHERTYPE_88A8 && +				 ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8) +				features |= NETIF_F_HW_VLAN_STAG_TX; +		} else if (insertion_support->inner != +			   VIRTCHNL_VLAN_UNSUPPORTED) { +			if (insertion_support->inner & +			    VIRTCHNL_VLAN_ETHERTYPE_8100 && +			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100) +				features |= NETIF_F_HW_VLAN_CTAG_TX; +		} + +		/* give priority to outer filtering and don't bother if both +		 * outer and inner filtering are enabled +		 */ +		ethertype_init = vlan_v2_caps->filtering.ethertype_init; +		if (filtering_support->outer != VIRTCHNL_VLAN_UNSUPPORTED) { +			if (filtering_support->outer & +			    VIRTCHNL_VLAN_ETHERTYPE_8100 && +			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100) +				features |= NETIF_F_HW_VLAN_CTAG_FILTER; +			if (filtering_support->outer & +			    VIRTCHNL_VLAN_ETHERTYPE_88A8 && +			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8) +				features |= NETIF_F_HW_VLAN_STAG_FILTER; +		} else if (filtering_support->inner != +			   VIRTCHNL_VLAN_UNSUPPORTED) { +			if (filtering_support->inner & +			    VIRTCHNL_VLAN_ETHERTYPE_8100 && +			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100) +				features |= NETIF_F_HW_VLAN_CTAG_FILTER; +			if (filtering_support->inner & +			    VIRTCHNL_VLAN_ETHERTYPE_88A8 && +			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8) +				features |= NETIF_F_HW_VLAN_STAG_FILTER; +		} +	} + +	return features; +} + +#define IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested, allowed, feature_bit) \ +	(!(((requested) & (feature_bit)) && \ +	   !((allowed) & (feature_bit)))) + +/** + * iavf_fix_netdev_vlan_features - fix NETDEV VLAN features based on support + * @adapter: board private structure + * @requested_features: stack requested NETDEV features + **/ +static netdev_features_t +iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter, +			      netdev_features_t requested_features) +{ +	netdev_features_t allowed_features; + +	allowed_features = iavf_get_netdev_vlan_hw_features(adapter) | +		iavf_get_netdev_vlan_features(adapter); + +	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features, +					      allowed_features, +					      NETIF_F_HW_VLAN_CTAG_TX)) +		requested_features &= ~NETIF_F_HW_VLAN_CTAG_TX; + +	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features, +					      allowed_features, +					      NETIF_F_HW_VLAN_CTAG_RX)) +		requested_features &= ~NETIF_F_HW_VLAN_CTAG_RX; + +	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features, +					      allowed_features, +					      NETIF_F_HW_VLAN_STAG_TX)) +		requested_features &= ~NETIF_F_HW_VLAN_STAG_TX; +	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features, +					      allowed_features, +					      NETIF_F_HW_VLAN_STAG_RX)) +		requested_features &= ~NETIF_F_HW_VLAN_STAG_RX; + +	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features, +					      allowed_features, +					      NETIF_F_HW_VLAN_CTAG_FILTER)) +		requested_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + +	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features, +					      allowed_features, +					      NETIF_F_HW_VLAN_STAG_FILTER)) +		requested_features &= ~NETIF_F_HW_VLAN_STAG_FILTER; + +	if ((requested_features & +	     (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX)) && +	    (requested_features & +	     (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX)) && +	    adapter->vlan_v2_caps.offloads.ethertype_match == +	    VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION) { +		netdev_warn(adapter->netdev, "cannot support CTAG and STAG VLAN stripping and/or insertion simultaneously since CTAG and STAG offloads are mutually exclusive, clearing STAG offload settings\n"); +		requested_features &= ~(NETIF_F_HW_VLAN_STAG_RX | +					NETIF_F_HW_VLAN_STAG_TX); +	} + +	return requested_features; +} + +/**   * iavf_fix_features - fix up the netdev feature bits   * @netdev: our net device   * @features: desired feature bits @@ -3503,12 +4176,7 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev,  {  	struct iavf_adapter *adapter = netdev_priv(netdev); -	if (!(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)) -		features &= ~(NETIF_F_HW_VLAN_CTAG_TX | -			      NETIF_F_HW_VLAN_CTAG_RX | -			      NETIF_F_HW_VLAN_CTAG_FILTER); - -	return features; +	return iavf_fix_netdev_vlan_features(adapter, features);  }  static const struct net_device_ops iavf_netdev_ops = { @@ -3560,39 +4228,11 @@ static int iavf_check_reset_complete(struct iavf_hw *hw)  int iavf_process_config(struct iavf_adapter *adapter)  {  	struct virtchnl_vf_resource *vfres = adapter->vf_res; -	int i, num_req_queues = adapter->num_req_queues; +	netdev_features_t hw_vlan_features, vlan_features;  	struct net_device *netdev = adapter->netdev; -	struct iavf_vsi *vsi = &adapter->vsi;  	netdev_features_t hw_enc_features;  	netdev_features_t hw_features; -	/* got VF config message back from PF, now we can parse it */ -	for (i = 0; i < vfres->num_vsis; i++) { -		if (vfres->vsi_res[i].vsi_type == VIRTCHNL_VSI_SRIOV) -			adapter->vsi_res = &vfres->vsi_res[i]; -	} -	if (!adapter->vsi_res) { -		dev_err(&adapter->pdev->dev, "No LAN VSI found\n"); -		return -ENODEV; -	} - -	if (num_req_queues && -	    num_req_queues > adapter->vsi_res->num_queue_pairs) { -		/* Problem.  The PF gave us fewer queues than what we had -		 * negotiated in our request.  Need a reset to see if we can't -		 * get back to a working state. -		 */ -		dev_err(&adapter->pdev->dev, -			"Requested %d queues, but PF only gave us %d.\n", -			num_req_queues, -			adapter->vsi_res->num_queue_pairs); -		adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED; -		adapter->num_req_queues = adapter->vsi_res->num_queue_pairs; -		iavf_schedule_reset(adapter); -		return -ENODEV; -	} -	adapter->num_req_queues = 0; -  	hw_enc_features = NETIF_F_SG			|  			  NETIF_F_IP_CSUM		|  			  NETIF_F_IPV6_CSUM		| @@ -3636,19 +4276,19 @@ int iavf_process_config(struct iavf_adapter *adapter)  	 */  	hw_features = hw_enc_features; -	/* Enable VLAN features if supported */ -	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) -		hw_features |= (NETIF_F_HW_VLAN_CTAG_TX | -				NETIF_F_HW_VLAN_CTAG_RX); +	/* get HW VLAN features that can be toggled */ +	hw_vlan_features = iavf_get_netdev_vlan_hw_features(adapter); +  	/* Enable cloud filter if ADQ is supported */  	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ)  		hw_features |= NETIF_F_HW_TC;  	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_USO)  		hw_features |= NETIF_F_GSO_UDP_L4; -	netdev->hw_features |= hw_features; +	netdev->hw_features |= hw_features | hw_vlan_features; +	vlan_features = iavf_get_netdev_vlan_features(adapter); -	netdev->features |= hw_features; +	netdev->features |= hw_features | vlan_features;  	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)  		netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; @@ -3673,21 +4313,6 @@ int iavf_process_config(struct iavf_adapter *adapter)  			netdev->features &= ~NETIF_F_GSO;  	} -	adapter->vsi.id = adapter->vsi_res->vsi_id; - -	adapter->vsi.back = adapter; -	adapter->vsi.base_vector = 1; -	adapter->vsi.work_limit = IAVF_DEFAULT_IRQ_WORK; -	vsi->netdev = adapter->netdev; -	vsi->qs_handle = adapter->vsi_res->qset_handle; -	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) { -		adapter->rss_key_size = vfres->rss_key_size; -		adapter->rss_lut_size = vfres->rss_lut_size; -	} else { -		adapter->rss_key_size = IAVF_HKEY_ARRAY_SIZE; -		adapter->rss_lut_size = IAVF_HLUT_ARRAY_SIZE; -	} -  	return 0;  } @@ -3957,6 +4582,7 @@ static void iavf_remove(struct pci_dev *pdev)  	if (iavf_lock_timeout(&adapter->crit_lock, 5000))  		dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__); +	dev_info(&adapter->pdev->dev, "Removing device\n");  	/* Shut down all the garbage mashers on the detention level */  	iavf_change_state(adapter, __IAVF_REMOVE);  	adapter->aq_required = 0; |