Intel-Wired-Lan Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Lobakin <alexandr.lobakin@intel.com>
To: intel-wired-lan@osuosl.org
Subject: [Intel-wired-lan] [PATCH net-next 08/19] iecm: add interrupts and configure netdev
Date: Fri, 28 Jan 2022 14:34:47 +0100	[thread overview]
Message-ID: <20220128133447.22242-1-alexandr.lobakin@intel.com> (raw)
In-Reply-To: <20220128001009.721392-9-alan.brady@intel.com>

From: Alan Brady <alan.brady@intel.com>
Date: Thu, 27 Jan 2022 16:09:58 -0800

> This finishes implementing init_task by adding everything we need to
> configure the netdevice for the vport and setup its interrupts.
> 
> Signed-off-by: Phani Burra <phani.r.burra@intel.com>
> Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
> Signed-off-by: Madhu Chittim <madhu.chittim@intel.com>
> Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
> Signed-off-by: Alice Michael <alice.michael@intel.com>
> Signed-off-by: Alan Brady <alan.brady@intel.com>
> ---
>  drivers/net/ethernet/intel/iecm/iecm_lib.c    | 813 +++++++++++++++++-
>  drivers/net/ethernet/intel/iecm/iecm_txrx.c   |  17 +
>  .../net/ethernet/intel/iecm/iecm_virtchnl.c   | 165 ++++
>  drivers/net/ethernet/intel/include/iecm.h     | 112 ++-
>  .../net/ethernet/intel/include/iecm_txrx.h    |   2 +
>  5 files changed, 1104 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/iecm/iecm_lib.c b/drivers/net/ethernet/intel/iecm/iecm_lib.c
> index aab8ee40424e..255b04c25683 100644
> --- a/drivers/net/ethernet/intel/iecm/iecm_lib.c
> +++ b/drivers/net/ethernet/intel/iecm/iecm_lib.c
> @@ -5,11 +5,35 @@
>  
>  #include "iecm.h"
>  
> +static const struct net_device_ops iecm_netdev_ops_splitq;
> +static const struct net_device_ops iecm_netdev_ops_singleq;
> +
>  const char * const iecm_vport_vc_state_str[] = {
>  	IECM_FOREACH_VPORT_VC_STATE(IECM_GEN_STRING)
>  };
>  EXPORT_SYMBOL(iecm_vport_vc_state_str);
>  
> +/**
> + * iecm_get_vport_index - Get the vport index
> + * @adapter: adapter structure to get the vports array
> + * @vport: vport pointer for which the index to find
> + */
> +static int iecm_get_vport_index(struct iecm_adapter *adapter,
> +				struct iecm_vport *vport)
> +{
> +	int i, err = -EINVAL;
> +
> +	if (!adapter->vports)
> +		return err;
> +
> +	for (i = 0; i < adapter->num_alloc_vport; i++) {
> +		if (adapter->vports[i] != vport)
> +			continue;
> +		return i;
> +	}
> +	return err;
> +}
> +
>  /**
>   * iecm_is_feature_ena - Determine if a particular feature is enabled
>   * @vport: vport to check
> @@ -29,6 +53,595 @@ bool iecm_is_feature_ena(struct iecm_vport *vport, netdev_features_t feature)
>  	return ena;
>  }
>  
> +/**
> + * iecm_is_vlan_cap_ena - Check if VLAN capability is enabled
> + * @adapter: pointer to adapter
> + * @vcaps: VLAN capability bit
> + *
> + * Returns true if VLAN capability is set, false otherwise
> + */
> +static bool iecm_is_vlan_cap_ena(struct iecm_adapter *adapter,
> +				 enum iecm_vlan_caps vcaps)
> +{
> +	if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_VLAN)) {
> +		struct virtchnl_vlan_supported_caps *offload;
> +
> +		if (!adapter->vlan_caps)
> +			return false;
> +
> +		switch (vcaps) {
> +		case IECM_CAP_VLAN_CTAG_INSERT:
> +			offload =
> +			&adapter->vlan_caps->offloads.insertion_support;
> +			if ((offload->outer & IECM_VLAN_8100) == IECM_VLAN_8100 ||
> +			    (offload->inner & IECM_VLAN_8100) == IECM_VLAN_8100)
> +				return true;
> +			break;
> +		case IECM_CAP_VLAN_STAG_INSERT:
> +			offload =
> +			&adapter->vlan_caps->offloads.insertion_support;
> +			if ((offload->outer & IECM_VLAN_88A8) == IECM_VLAN_88A8)
> +				return true;
> +			break;
> +		case IECM_CAP_VLAN_CTAG_STRIP:
> +			offload =
> +			&adapter->vlan_caps->offloads.stripping_support;
> +			if ((offload->outer & IECM_VLAN_8100) == IECM_VLAN_8100 ||
> +			    (offload->inner & IECM_VLAN_8100) == IECM_VLAN_8100)
> +				return true;
> +			break;
> +		case IECM_CAP_VLAN_STAG_STRIP:
> +			offload =
> +			&adapter->vlan_caps->offloads.stripping_support;
> +			if ((offload->outer & IECM_VLAN_88A8) == IECM_VLAN_88A8)
> +				return true;
> +			break;
> +		case IECM_CAP_VLAN_CTAG_ADD_DEL:
> +			offload =
> +			&adapter->vlan_caps->filtering.filtering_support;
> +			if ((offload->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) ||
> +			    (offload->inner & VIRTCHNL_VLAN_ETHERTYPE_8100))
> +				return true;
> +			break;
> +		case IECM_CAP_VLAN_STAG_ADD_DEL:
> +			offload =
> +			&adapter->vlan_caps->filtering.filtering_support;
> +			if ((offload->outer & VIRTCHNL_VLAN_ETHERTYPE_88A8) ||
> +			    (offload->inner & VIRTCHNL_VLAN_ETHERTYPE_88A8))
> +				return true;
> +			break;
> +		default:
> +			dev_err(&adapter->pdev->dev, "Invalid VLAN capability %d\n",
> +				vcaps);
> +			return false;
> +		}
> +	} else if (iecm_is_cap_ena(adapter, IECM_BASE_CAPS,
> +				   VIRTCHNL2_CAP_VLAN)) {
> +		switch (vcaps) {
> +		case IECM_CAP_VLAN_CTAG_INSERT:
> +		case IECM_CAP_VLAN_CTAG_STRIP:
> +		case IECM_CAP_VLAN_CTAG_ADD_DEL:
> +			return true;
> +		default:
> +			return false;
> +		}
> +	}
> +
> +	return false;
> +}
> +
> +/**
> + * iecm_netdev_to_vport - get a vport handle from a netdev
> + * @netdev: network interface device structure
> + */
> +struct iecm_vport *iecm_netdev_to_vport(struct net_device *netdev)
> +{
> +	struct iecm_netdev_priv *np = netdev_priv(netdev);
> +
> +	return np->vport;
> +}
> +
> +/**
> + * iecm_mb_intr_rel_irq - Free the IRQ association with the OS
> + * @adapter: adapter structure
> + */
> +static void iecm_mb_intr_rel_irq(struct iecm_adapter *adapter)
> +{
> +	int irq_num;
> +
> +	irq_num = adapter->msix_entries[0].vector;
> +	free_irq(irq_num, adapter);
> +}
> +
> +/**
> + * iecm_intr_rel - Release interrupt capabilities and free memory
> + * @adapter: adapter to disable interrupts on
> + */
> +static void iecm_intr_rel(struct iecm_adapter *adapter)
> +{
> +	if (!adapter->msix_entries)
> +		return;
> +	clear_bit(__IECM_MB_INTR_MODE, adapter->flags);
> +	clear_bit(__IECM_MB_INTR_TRIGGER, adapter->flags);
> +	iecm_mb_intr_rel_irq(adapter);
> +
> +	pci_free_irq_vectors(adapter->pdev);
> +	if (adapter->dev_ops.vc_ops.dealloc_vectors) {
> +		int err;
> +
> +		err = adapter->dev_ops.vc_ops.dealloc_vectors(adapter);
> +		if (err) {
> +			dev_err(&adapter->pdev->dev,
> +				"Failed to deallocate vectors: %d\n", err);
> +		}
> +	}
> +	kfree(adapter->msix_entries);
> +	adapter->msix_entries = NULL;
> +	kfree(adapter->req_vec_chunks);
> +	adapter->req_vec_chunks = NULL;
> +}
> +
> +/**
> + * iecm_mb_intr_clean - Interrupt handler for the mailbox
> + * @irq: interrupt number
> + * @data: pointer to the adapter structure
> + */
> +static irqreturn_t iecm_mb_intr_clean(int __always_unused irq, void *data)
> +{
> +	struct iecm_adapter *adapter = (struct iecm_adapter *)data;
> +
> +	set_bit(__IECM_MB_INTR_TRIGGER, adapter->flags);
> +	queue_delayed_work(adapter->serv_wq, &adapter->serv_task,
> +			   msecs_to_jiffies(0));
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * iecm_mb_irq_enable - Enable MSIX interrupt for the mailbox
> + * @adapter: adapter to get the hardware address for register write
> + */
> +static void iecm_mb_irq_enable(struct iecm_adapter *adapter)
> +{
> +	struct iecm_hw *hw = &adapter->hw;
> +	struct iecm_intr_reg *intr = &adapter->mb_vector.intr_reg;

Please don't break Reverse Christmas Tree declaration style. *intr
doesn't depend on *hw.

> +	u32 val;
> +
> +	val = intr->dyn_ctl_intena_m | intr->dyn_ctl_itridx_m;
> +	wr32(hw, intr->dyn_ctl, val);
> +	wr32(hw, intr->icr_ena, intr->icr_ena_ctlq_m);
> +}
> +
> +/**
> + * iecm_mb_intr_req_irq - Request irq for the mailbox interrupt
> + * @adapter: adapter structure to pass to the mailbox irq handler
> + */
> +static int iecm_mb_intr_req_irq(struct iecm_adapter *adapter)
> +{
> +	struct iecm_q_vector *mb_vector = &adapter->mb_vector;
> +	int irq_num, mb_vidx = 0, err;
> +
> +	irq_num = adapter->msix_entries[mb_vidx].vector;
> +	snprintf(mb_vector->name, sizeof(mb_vector->name) - 1,
> +		 "%s-%s-%d", dev_driver_string(&adapter->pdev->dev),
> +		 "Mailbox", mb_vidx);
> +	err = request_irq(irq_num, adapter->irq_mb_handler, 0,
> +			  mb_vector->name, adapter);
> +	if (err) {
> +		dev_err(&adapter->pdev->dev,
> +			"Request_irq for mailbox failed, error: %d\n", err);
> +		return err;
> +	}
> +	set_bit(__IECM_MB_INTR_MODE, adapter->flags);
> +	return 0;
> +}
> +
> +/**
> + * iecm_get_mb_vec_id - Get vector index for mailbox
> + * @adapter: adapter structure to access the vector chunks
> + *
> + * The first vector id in the requested vector chunks from the CP is for
> + * the mailbox
> + */
> +static void iecm_get_mb_vec_id(struct iecm_adapter *adapter)
> +{
> +	if (adapter->req_vec_chunks) {
> +		struct virtchnl2_get_capabilities *caps;
> +
> +		caps = (struct virtchnl2_get_capabilities *)adapter->caps;
> +		adapter->mb_vector.v_idx = le16_to_cpu(caps->mailbox_vector_id);
> +	} else {
> +		adapter->mb_vector.v_idx = 0;
> +	}
> +}
> +
> +/**
> + * iecm_mb_intr_init - Initialize the mailbox interrupt
> + * @adapter: adapter structure to store the mailbox vector
> + */
> +static int iecm_mb_intr_init(struct iecm_adapter *adapter)
> +{
> +	adapter->dev_ops.reg_ops.mb_intr_reg_init(adapter);
> +	adapter->irq_mb_handler = iecm_mb_intr_clean;
> +	return iecm_mb_intr_req_irq(adapter);
> +}
> +
> +/**
> + * iecm_intr_distribute - Distribute MSIX vectors
> + * @adapter: adapter structure to get the vports
> + * @pre_req: before or after msi request
> + *
> + * Distribute the MSIX vectors acquired from the OS to the vports based on the
> + * num of vectors requested by each vport
> + */
> +static int
> +iecm_intr_distribute(struct iecm_adapter *adapter, bool pre_req)
> +{
> +	struct iecm_vport *vport = adapter->vports[0];
> +	int err = 0;
> +
> +	if (pre_req) {
> +		u16 vecs_avail;
> +
> +		vecs_avail = iecm_get_reserved_vecs(adapter);
> +		if (vecs_avail < IECM_MIN_VEC) {
> +			return -EAGAIN;
> +		} else if (vecs_avail == IECM_MIN_VEC) {
> +			vport->num_q_vectors = IECM_MIN_Q_VEC;
> +		} else {
> +			vport->num_q_vectors = vecs_avail - IECM_NONQ_VEC -
> +						IECM_MAX_RDMA_VEC;
> +		}
> +	} else {
> +		if (adapter->num_msix_entries != adapter->num_req_msix)
> +			vport->num_q_vectors = adapter->num_msix_entries -
> +					       IECM_NONQ_VEC;
> +	}
> +
> +	return err;
> +}
> +
> +/**
> + * iecm_intr_req - Request interrupt capabilities
> + * @adapter: adapter to enable interrupts on
> + *
> + * Returns 0 on success, negative on failure
> + */
> +static int iecm_intr_req(struct iecm_adapter *adapter)
> +{
> +	int min_vectors, max_vectors, err = 0;
> +	int num_q_vecs, total_num_vecs;
> +	u16 vecids[IECM_MAX_VECIDS];
> +	unsigned int vector;
> +	int v_actual;
> +
> +	err = iecm_intr_distribute(adapter, true);
> +	if (err)
> +		return err;
> +
> +	num_q_vecs = adapter->vports[0]->num_q_vectors;
> +
> +	total_num_vecs = num_q_vecs + IECM_NONQ_VEC;
> +
> +	if (adapter->dev_ops.vc_ops.alloc_vectors) {
> +		err = adapter->dev_ops.vc_ops.alloc_vectors(adapter,
> +							    num_q_vecs);
> +		if (err) {
> +			dev_err(&adapter->pdev->dev,
> +				"Failed to allocate vectors: %d\n", err);
> +			return -EAGAIN;
> +		}
> +	}
> +
> +	min_vectors = IECM_MIN_VEC;
> +	max_vectors = total_num_vecs;
> +	v_actual = pci_alloc_irq_vectors(adapter->pdev, min_vectors,
> +					 max_vectors, PCI_IRQ_MSIX);
> +	if (v_actual < 0) {
> +		dev_err(&adapter->pdev->dev, "Failed to allocate MSIX vectors: %d\n",
> +			v_actual);
> +		if (adapter->dev_ops.vc_ops.dealloc_vectors)
> +			adapter->dev_ops.vc_ops.dealloc_vectors(adapter);
> +		return -EAGAIN;
> +	}
> +
> +	adapter->msix_entries = kcalloc(v_actual, sizeof(struct msix_entry),
> +					GFP_KERNEL);
> +
> +	if (!adapter->msix_entries) {
> +		pci_free_irq_vectors(adapter->pdev);
> +		if (adapter->dev_ops.vc_ops.dealloc_vectors)
> +			adapter->dev_ops.vc_ops.dealloc_vectors(adapter);
> +		return -ENOMEM;
> +	}
> +
> +	iecm_get_mb_vec_id(adapter);
> +
> +	if (adapter->req_vec_chunks) {
> +		struct virtchnl2_vector_chunks *vchunks;
> +		struct virtchnl2_alloc_vectors *ac;
> +
> +		ac = adapter->req_vec_chunks;
> +		vchunks = &ac->vchunks;
> +
> +		iecm_get_vec_ids(adapter, vecids, IECM_MAX_VECIDS, vchunks);
> +	} else {
> +		int i = 0;
> +
> +		for (i = 0; i < v_actual; i++)
> +			vecids[i] = i;
> +	}
> +
> +	for (vector = 0; vector < v_actual; vector++) {
> +		adapter->msix_entries[vector].entry = vecids[vector];
> +		adapter->msix_entries[vector].vector =
> +			pci_irq_vector(adapter->pdev, vector);
> +	}
> +	adapter->num_msix_entries = v_actual;
> +	adapter->num_req_msix = total_num_vecs;
> +
> +	iecm_intr_distribute(adapter, false);
> +
> +	err = iecm_mb_intr_init(adapter);
> +	if (err)
> +		goto intr_rel;
> +	iecm_mb_irq_enable(adapter);
> +	return err;
> +
> +intr_rel:
> +	iecm_intr_rel(adapter);
> +	return err;
> +}
> +
> +/**
> + * iecm_find_mac_filter - Search filter list for specific mac filter
> + * @vport: main vport structure
> + * @macaddr: the MAC address
> + *
> + * Returns ptr to the filter object or NULL. Must be called while holding the
> + * mac_filter_list_lock.
> + **/
> +static struct
> +iecm_mac_filter *iecm_find_mac_filter(struct iecm_vport *vport,
> +				      const u8 *macaddr)
> +{
> +	struct iecm_adapter *adapter = vport->adapter;
> +	struct iecm_mac_filter *f;
> +
> +	if (!macaddr)
> +		return NULL;
> +
> +	list_for_each_entry(f, &adapter->config_data.mac_filter_list, list) {
> +		if (ether_addr_equal(macaddr, f->macaddr))
> +			return f;
> +	}

Excessive braces again.

> +	return NULL;
> +}
> +
> +/**
> + * __iecm_add_mac_filter - Add mac filter helper function
> + * @vport: main vport struct
> + * @macaddr: address to add
> + *
> + * Takes mac_filter_list_lock spinlock to add new filter to list.
> + */
> +static struct
> +iecm_mac_filter *__iecm_add_mac_filter(struct iecm_vport *vport,
> +				       const u8 *macaddr)
> +{
> +	struct iecm_adapter *adapter = vport->adapter;
> +	struct iecm_mac_filter *f = NULL;
> +
> +	spin_lock_bh(&adapter->mac_filter_list_lock);
> +	f = iecm_find_mac_filter(vport, macaddr);
> +	if (!f) {
> +		f = kzalloc(sizeof(*f), GFP_ATOMIC);
> +		if (!f) {
> +			dev_err(&adapter->pdev->dev, "Failed to allocate filter: %pM",
> +				macaddr);
> +			goto error;
> +		}
> +
> +		ether_addr_copy(f->macaddr, macaddr);
> +
> +		list_add_tail(&f->list, &adapter->config_data.mac_filter_list);
> +		f->add = true;
> +	} else {
> +		f->remove = false;
> +	}

	if (f) {
		f->remove = false;
		goto error; /* It's better to rename it */
	}

	f = kzalloc(...

-1 indent level.

> +error:
> +	spin_unlock_bh(&adapter->mac_filter_list_lock);
> +
> +	return f;
> +}
> +
> +/**
> + * iecm_add_mac_filter - Add a mac filter to the filter list
> + * @vport: main vport structure
> + * @macaddr: the MAC address
> + *
> + * Returns ptr to the filter or NULL on error. If interface is up, we'll also
> + * send the virtchnl message to tell hardware about the filter.
> + **/
> +static struct iecm_mac_filter *iecm_add_mac_filter(struct iecm_vport *vport,
> +						   const u8 *macaddr)
> +{
> +	struct iecm_mac_filter *f;
> +
> +	if (!macaddr)
> +		return NULL;
> +
> +	f = __iecm_add_mac_filter(vport, macaddr);
> +	if (!f)
> +		return NULL;
> +
> +	if (vport->adapter->state == __IECM_UP)
> +		iecm_add_del_ether_addrs(vport, true, false);
> +
> +	return f;
> +}
> +
> +/**
> + * iecm_init_mac_addr - initialize mac address for vport
> + * @vport: main vport structure
> + * @netdev: pointer to netdev struct associated with this vport
> + */
> +static int iecm_init_mac_addr(struct iecm_vport *vport,
> +			      struct net_device *netdev)
> +{
> +	struct iecm_adapter *adapter = vport->adapter;
> +
> +	if (!is_valid_ether_addr(vport->default_mac_addr)) {
> +		if (!iecm_is_cap_ena(vport->adapter, IECM_OTHER_CAPS,
> +				     VIRTCHNL2_CAP_MACFILTER)) {
> +			dev_err(&adapter->pdev->dev,
> +				"MAC address not provided and capability is not set\n");
> +			return -EINVAL;
> +		}
> +
> +		dev_info(&adapter->pdev->dev, "Invalid MAC address %pM, using random\n",
> +			 vport->default_mac_addr);
> +		eth_hw_addr_random(netdev);
> +
> +		if (!iecm_add_mac_filter(vport, netdev->dev_addr))
> +			return -ENOMEM;
> +
> +		ether_addr_copy(vport->default_mac_addr, netdev->dev_addr);
> +	} else {
> +		dev_addr_mod(netdev, 0, vport->default_mac_addr, ETH_ALEN);
> +		ether_addr_copy(netdev->perm_addr, vport->default_mac_addr);
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * iecm_cfg_netdev - Allocate, configure and register a netdev
> + * @vport: main vport structure
> + *
> + * Returns 0 on success, negative value on failure.
> + */
> +static int iecm_cfg_netdev(struct iecm_vport *vport)
> +{
> +	struct iecm_adapter *adapter = vport->adapter;
> +	netdev_features_t dflt_features;
> +	netdev_features_t offloads = 0;
> +	struct iecm_netdev_priv *np;
> +	struct net_device *netdev;
> +	u16 max_q;
> +	int err;
> +
> +	lockdep_assert_held(&adapter->sw_mutex);
> +
> +	/* It's possible we already have a netdev allocated and registered for
> +	 * this vport
> +	 */
> +	if (adapter->netdevs[vport->idx]) {
> +		netdev = adapter->netdevs[vport->idx];
> +		np = netdev_priv(netdev);
> +		np->vport = vport;
> +		vport->netdev = netdev;
> +
> +		return iecm_init_mac_addr(vport, netdev);
> +	}
> +
> +	max_q = adapter->max_queue_limit;
> +
> +	netdev = alloc_etherdev_mqs(sizeof(struct iecm_netdev_priv),
> +				    max_q, max_q);
> +	if (!netdev)
> +		return -ENOMEM;
> +	vport->netdev = netdev;
> +	np = netdev_priv(netdev);
> +	np->vport = vport;
> +
> +	err = iecm_init_mac_addr(vport, netdev);
> +	if (err)
> +		goto err;
> +
> +	/* assign netdev_ops */
> +	if (iecm_is_queue_model_split(vport->txq_model))
> +		netdev->netdev_ops = &iecm_netdev_ops_splitq;
> +	else
> +		netdev->netdev_ops = &iecm_netdev_ops_singleq;
> +
> +	/* setup watchdog timeout value to be 5 second */
> +	netdev->watchdog_timeo = 5 * HZ;
> +
> +	/* configure default MTU size */
> +	netdev->min_mtu = ETH_MIN_MTU;
> +	netdev->max_mtu = vport->max_mtu;
> +
> +	dflt_features = NETIF_F_SG	|
> +			NETIF_F_HIGHDMA;
> +
> +	if (iecm_is_cap_ena_all(adapter, IECM_RSS_CAPS, IECM_CAP_RSS))
> +		dflt_features |= NETIF_F_RXHASH;
> +	if (iecm_is_cap_ena_all(adapter, IECM_CSUM_CAPS, IECM_CAP_RX_CSUM_L4V4))
> +		dflt_features |= NETIF_F_IP_CSUM;
> +	if (iecm_is_cap_ena_all(adapter, IECM_CSUM_CAPS, IECM_CAP_RX_CSUM_L4V6))
> +		dflt_features |= NETIF_F_IPV6_CSUM;
> +	if (iecm_is_cap_ena(adapter, IECM_CSUM_CAPS, IECM_CAP_RX_CSUM))
> +		dflt_features |= NETIF_F_RXCSUM;
> +	if (iecm_is_cap_ena_all(adapter, IECM_CSUM_CAPS, IECM_CAP_SCTP_CSUM))
> +		dflt_features |= NETIF_F_SCTP_CRC;
> +
> +	if (iecm_is_vlan_cap_ena(adapter, IECM_CAP_VLAN_CTAG_INSERT))
> +		dflt_features |= IECM_F_HW_VLAN_CTAG_TX;
> +	if (iecm_is_vlan_cap_ena(adapter, IECM_CAP_VLAN_CTAG_STRIP))
> +		dflt_features |= IECM_F_HW_VLAN_CTAG_RX;
> +	if (iecm_is_vlan_cap_ena(adapter, IECM_CAP_VLAN_CTAG_ADD_DEL))
> +		dflt_features |= IECM_F_HW_VLAN_CTAG_FILTER;
> +
> +	if (iecm_is_vlan_cap_ena(adapter, IECM_CAP_VLAN_STAG_INSERT))
> +		dflt_features |= NETIF_F_HW_VLAN_STAG_TX;
> +	if (iecm_is_vlan_cap_ena(adapter, IECM_CAP_VLAN_STAG_STRIP))
> +		dflt_features |= NETIF_F_HW_VLAN_STAG_RX;
> +	if (iecm_is_vlan_cap_ena(adapter, IECM_CAP_VLAN_STAG_ADD_DEL))
> +		dflt_features |= NETIF_F_HW_VLAN_STAG_FILTER;
> +	/* Enable cloud filter if ADQ is supported */
> +	if (iecm_is_cap_ena(adapter, IECM_BASE_CAPS, VIRTCHNL2_CAP_ADQ) ||
> +	    iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_ADQ))
> +		dflt_features |= NETIF_F_HW_TC;
> +	if (iecm_is_cap_ena(adapter, IECM_SEG_CAPS, VIRTCHNL2_CAP_SEG_IPV4_TCP))
> +		dflt_features |= NETIF_F_TSO;
> +	if (iecm_is_cap_ena(adapter, IECM_SEG_CAPS, VIRTCHNL2_CAP_SEG_IPV6_TCP))
> +		dflt_features |= NETIF_F_TSO6;
> +	if (iecm_is_cap_ena_all(adapter, IECM_SEG_CAPS,
> +				VIRTCHNL2_CAP_SEG_IPV4_UDP |
> +				VIRTCHNL2_CAP_SEG_IPV6_UDP))
> +		dflt_features |= NETIF_F_GSO_UDP_L4;
> +	if (iecm_is_cap_ena_all(adapter, IECM_RSC_CAPS, IECM_CAP_RSC))
> +		offloads |= NETIF_F_GRO_HW;

I see `offloads` being used only here, |= -> =.

> +	netdev->features |= dflt_features;
> +	netdev->hw_features |= dflt_features | offloads;
> +	netdev->hw_enc_features |= dflt_features | offloads;
> +
> +	SET_NETDEV_DEV(netdev, &adapter->pdev->dev);
> +
> +	/* carrier off on init to avoid Tx hangs */
> +	netif_carrier_off(netdev);
> +
> +	/* make sure transmit queues start off as stopped */
> +	netif_tx_stop_all_queues(netdev);
> +
> +	/* register last */
> +	err = register_netdev(netdev);
> +	if (err)
> +		goto err;
> +
> +	/* The vport can be arbitrarily released so we need to also track
> +	 * netdevs in the adapter struct
> +	 */
> +	adapter->netdevs[vport->idx] = netdev;
> +
> +	return 0;
> +err:
> +	free_netdev(vport->netdev);
> +	vport->netdev = NULL;
> +
> +	return err;
> +}
> +
>  /**
>   * iecm_cfg_hw - Initialize HW struct
>   * @adapter: adapter to setup hw struct for
> @@ -77,6 +690,24 @@ static int iecm_get_free_slot(void *array, int size, int curr)
>  	return next;
>  }
>  
> +/**
> + * iecm_decfg_netdev - Unregister the netdev
> + * @vport: vport for which netdev to be unregistred
> + */
> +static void iecm_decfg_netdev(struct iecm_vport *vport)
> +{
> +	struct iecm_adapter *adapter = vport->adapter;
> +
> +	if (!vport->netdev)
> +		return;
> +
> +	unregister_netdev(vport->netdev);
> +	free_netdev(vport->netdev);
> +	vport->netdev = NULL;
> +
> +	adapter->netdevs[vport->idx] = NULL;
> +}
> +
>  /**
>   * iecm_vport_rel - Delete a vport and free its resources
>   * @vport: the vport being removed
> @@ -102,6 +733,8 @@ static void iecm_vport_rel_all(struct iecm_adapter *adapter)
>  		if (!adapter->vports[i])
>  			continue;
>  
> +		if (!test_bit(__IECM_HR_RESET_IN_PROG, adapter->flags))
> +			iecm_decfg_netdev(adapter->vports[i]);
>  		iecm_vport_rel(adapter->vports[i]);
>  		adapter->vports[i] = NULL;
>  		adapter->next_vport = 0;
> @@ -151,7 +784,7 @@ iecm_vport_alloc(struct iecm_adapter *adapter, int vport_id)
>  	adapter->num_alloc_vport++;
>  
>  	/* Setup default MSIX irq handler for the vport */
> -	vport->irq_q_handler = NULL;
> +	vport->irq_q_handler = iecm_vport_intr_clean_queues;
>  	vport->q_vector_base = IECM_NONQ_VEC;
>  
>  	mutex_init(&vport->stop_mutex);
> @@ -184,8 +817,94 @@ static void iecm_statistics_task(struct work_struct *work)
>   *
>   */
>  static void iecm_service_task(struct work_struct *work)
> +{
> +	struct iecm_adapter *adapter = container_of(work,
> +						    struct iecm_adapter,
> +						    serv_task.work);

	struct iecm_adapter *adapter;

	adapter = container_of(work, typeof(*adapter), serv_task.work);

Same line count, but more elegant with no line wraps.

> +
> +	if (test_bit(__IECM_MB_INTR_MODE, adapter->flags)) {
> +		if (test_and_clear_bit(__IECM_MB_INTR_TRIGGER,
> +				       adapter->flags)) {
> +			iecm_recv_mb_msg(adapter, VIRTCHNL_OP_UNKNOWN, NULL, 0);
> +			iecm_mb_irq_enable(adapter);
> +		}
> +	} else {
> +		iecm_recv_mb_msg(adapter, VIRTCHNL_OP_UNKNOWN, NULL, 0);
> +	}
> +
> +	if (iecm_is_reset_detected(adapter) &&
> +	    !iecm_is_reset_in_prog(adapter)) {
> +		dev_info(&adapter->pdev->dev, "HW reset detected\n");
> +		set_bit(__IECM_HR_FUNC_RESET, adapter->flags);
> +		queue_delayed_work(adapter->vc_event_wq,
> +				   &adapter->vc_event_task,
> +				   msecs_to_jiffies(10));
> +	}
> +
> +	queue_delayed_work(adapter->serv_wq, &adapter->serv_task,
> +			   msecs_to_jiffies(300));
> +}
> +
> +/* iecm_set_vlan_offload_features - set vlan offload features
> + * @netdev: netdev structure
> + * @prev_features: previously set features
> + * @features: current features received from user
> + *
> + * Returns 0 on success, error value on failure
> + */
> +static int
> +iecm_set_vlan_offload_features(struct net_device *netdev,
> +			       netdev_features_t prev_features,
> +			       netdev_features_t features)
> +{
> +	struct iecm_vport *vport = iecm_netdev_to_vport(netdev);
> +	bool stripping_ena = true, insertion_ena = true;
> +	struct iecm_virtchnl_ops *vc_ops;
> +	u16 vlan_ethertype = 0;
> +
> +	vc_ops = &vport->adapter->dev_ops.vc_ops;
> +	/* 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)))
> +		stripping_ena = false;
> +	if (!(features & (NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_VLAN_CTAG_TX)))
> +		insertion_ena = false;
> +
> +	vport->adapter->config_data.vlan_ethertype = vlan_ethertype;
> +
> +	vc_ops->strip_vlan_msg(vport, stripping_ena);
> +	if (vc_ops->insert_vlan_msg)
> +		vc_ops->insert_vlan_msg(vport, insertion_ena);
> +
> +	return 0;
> +}
> +
> +/**
> + * iecm_vport_open - Bring up a vport
> + * @vport: vport to bring up
> + * @alloc_res: allocate queue resources
> + */
> +static int iecm_vport_open(struct iecm_vport *vport, bool alloc_res)
>  {
>  	/* stub */
> +	return 0;
>  }
>  
>  /**
> @@ -206,6 +925,7 @@ static void iecm_init_task(struct work_struct *work)
>  	struct iecm_vport *vport;
>  	struct pci_dev *pdev;
>  	int vport_id, err;
> +	int index;
>  
>  	err = adapter->dev_ops.vc_ops.core_init(adapter, &vport_id);
>  	if (err)
> @@ -219,6 +939,65 @@ static void iecm_init_task(struct work_struct *work)
>  			err);
>  		return;
>  	}
> +	/* Start the service task before requesting vectors. This will ensure
> +	 * vector information response from mailbox is handled
> +	 */
> +	queue_delayed_work(adapter->serv_wq, &adapter->serv_task,
> +			   msecs_to_jiffies(5 * (pdev->devfn & 0x07)));
> +	err = iecm_intr_req(adapter);
> +	if (err) {
> +		dev_err(&pdev->dev, "failed to enable interrupt vectors: %d\n",
> +			err);
> +		goto intr_req_err;
> +	}
> +	err = iecm_send_vlan_v2_caps_msg(adapter);
> +	if (err)
> +		goto vlan_v2_caps_failed;
> +
> +	err = adapter->dev_ops.vc_ops.get_supported_desc_ids(vport);
> +	if (err) {
> +		dev_err(&pdev->dev, "failed to get required descriptor ids\n");
> +		goto rxdids_failed;
> +	}
> +
> +	if (iecm_cfg_netdev(vport))
> +		goto cfg_netdev_err;
> +
> +	if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_VLAN) ||
> +	    iecm_is_cap_ena(adapter, IECM_BASE_CAPS, VIRTCHNL2_CAP_VLAN)) {
> +		err = iecm_set_vlan_offload_features(vport->netdev, 0,
> +						     vport->netdev->features);
> +		if (err)
> +			goto cfg_netdev_err;
> +	}
> +
> +	err = adapter->dev_ops.vc_ops.get_ptype(vport);
> +	if (err)
> +		goto cfg_netdev_err;
> +	queue_delayed_work(adapter->stats_wq, &adapter->stats_task,
> +			   msecs_to_jiffies(10 * (pdev->devfn & 0x07)));
> +	set_bit(__IECM_VPORT_INIT_PROMISC, vport->flags);
> +	/* Once state is put into DOWN, driver is ready for dev_open */
> +	adapter->state = __IECM_DOWN;
> +	if (test_and_clear_bit(__IECM_UP_REQUESTED, adapter->flags))
> +		iecm_vport_open(vport, true);
> +
> +	/* Clear the reset flag unconditionally here in case we were in reset
> +	 * and the link was down
> +	 */
> +	clear_bit(__IECM_HR_RESET_IN_PROG, vport->adapter->flags);
> +
> +	return;
> +
> +vlan_v2_caps_failed:
> +rxdids_failed:
> +cfg_netdev_err:

No reason to declare 3 labels at the same point.

> +	iecm_intr_rel(adapter);
> +intr_req_err:
> +	index = iecm_get_vport_index(adapter, vport);
> +	if (index >= 0)
> +		adapter->vports[index] = NULL;
> +	iecm_vport_rel(vport);
>  }
>  
>  /**
> @@ -614,3 +1393,35 @@ void iecm_free_dma_mem(struct iecm_hw *hw, struct iecm_dma_mem *mem)
>  	mem->va = NULL;
>  	mem->pa = 0;
>  }
> +
> +static const struct net_device_ops iecm_netdev_ops_splitq = {
> +	.ndo_open = NULL,
> +	.ndo_stop = NULL,
> +	.ndo_start_xmit = NULL,
> +	.ndo_set_rx_mode = NULL,
> +	.ndo_validate_addr = eth_validate_addr,

eth_validate_addr() (or ether_addr_valid()) gets run by default when
no .ndo_validate_addr is specified. It's redundant to declare it
here.

> +	.ndo_set_mac_address = NULL,
> +	.ndo_change_mtu = NULL,
> +	.ndo_get_stats64 = NULL,
> +	.ndo_fix_features = NULL,
> +	.ndo_set_features = NULL,
> +	.ndo_vlan_rx_add_vid = NULL,
> +	.ndo_vlan_rx_kill_vid = NULL,
> +	.ndo_setup_tc = NULL,

Non-initialized members get zeroed by default, NULLing them is
excessive.

> +};
> +
> +static const struct net_device_ops iecm_netdev_ops_singleq = {
> +	.ndo_open = NULL,
> +	.ndo_stop = NULL,
> +	.ndo_start_xmit = NULL,
> +	.ndo_set_rx_mode = NULL,
> +	.ndo_validate_addr = eth_validate_addr,
> +	.ndo_set_mac_address = NULL,
> +	.ndo_change_mtu = NULL,
> +	.ndo_get_stats64 = NULL,
> +	.ndo_fix_features = NULL,
> +	.ndo_set_features = NULL,
> +	.ndo_vlan_rx_add_vid = NULL,
> +	.ndo_vlan_rx_kill_vid = NULL,
> +	.ndo_setup_tc           = NULL,

Same 2 previous points.

.ndo_setup_tc assignment indentation is weird. Either align all the
initializers with tabs or don't align at all (both are valid cases).

> +};
> diff --git a/drivers/net/ethernet/intel/iecm/iecm_txrx.c b/drivers/net/ethernet/intel/iecm/iecm_txrx.c
> index bd0cfd89bf03..bb7f5830cffb 100644
> --- a/drivers/net/ethernet/intel/iecm/iecm_txrx.c
> +++ b/drivers/net/ethernet/intel/iecm/iecm_txrx.c
> @@ -218,6 +218,23 @@ const struct iecm_rx_ptype_decoded iecm_ptype_lookup[IECM_RX_MAX_PTYPE] = {
>  };
>  EXPORT_SYMBOL(iecm_ptype_lookup);
>  
> +/**
> + * iecm_vport_intr_clean_queues - MSIX mode Interrupt Handler
> + * @irq: interrupt number
> + * @data: pointer to a q_vector
> + *
> + */
> +irqreturn_t
> +iecm_vport_intr_clean_queues(int __always_unused irq, void *data)
> +{
> +	struct iecm_q_vector *q_vector = (struct iecm_q_vector *)data;
> +
> +	q_vector->total_events++;
> +	napi_schedule(&q_vector->napi);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  /**
>   * iecm_vport_init_num_qs - Initialize number of queues
>   * @vport: vport to initialize queues
> diff --git a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
> index c4ae56897d1b..b91716aeef6f 100644
> --- a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
> +++ b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
> @@ -2731,6 +2731,45 @@ static int iecm_send_insert_vlan_msg(struct iecm_vport *vport, bool ena)
>  	return err;
>  }
>  
> +/**
> + * iecm_send_vlan_v2_caps_msg - send virtchnl get offload VLAN V2 caps message
> + * @adapter: adapter info struct
> + *
> + * Returns 0 on success and if VLAN V1 capability is set`, negative on failure.
> + */
> +int iecm_send_vlan_v2_caps_msg(struct iecm_adapter *adapter)
> +{
> +	int err = 0;
> +
> +	if (!iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_VLAN))
> +		return err;
> +
> +	err = iecm_send_mb_msg(adapter, VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS,
> +			       0, NULL);
> +	if (err)
> +		return err;
> +
> +	err = iecm_min_wait_for_event(adapter, IECM_VC_OFFLOAD_VLAN_V2_CAPS,
> +				      IECM_VC_OFFLOAD_VLAN_V2_CAPS_ERR);
> +
> +	if (err) {
> +		dev_err(&adapter->pdev->dev, "Failed to recv get caps");
> +		return err;
> +	}
> +
> +	if (!adapter->vlan_caps) {
> +		adapter->vlan_caps =
> +		  kzalloc(sizeof(*adapter->vlan_caps), GFP_KERNEL);
> +		if (!adapter->vlan_caps)
> +			return -ENOMEM;
> +	}
> +
> +	memcpy(adapter->vlan_caps,
> +	       adapter->vc_msg, sizeof(*adapter->vlan_caps));
> +
> +	return err;
> +}
> +
>  /**
>   * iecm_fill_ptype_lookup - Fill L3 specific fields in ptype lookup table
>   * @ptype: ptype lookup table
> @@ -3580,6 +3619,132 @@ static unsigned int iecm_get_max_tx_bufs(struct iecm_adapter *adapter)
>  	return ((struct virtchnl2_get_capabilities *)adapter->caps)->max_sg_bufs_per_tx_pkt;
>  }
>  
> +/**
> + * iecm_add_del_ether_addrs
> + * @vport: virtual port data structure
> + * @add: Add or delete flag
> + * @async: Don't wait for return message
> + *
> + * Request that the PF add or delete one or more addresses to our filters.
> + **/
> +void iecm_add_del_ether_addrs(struct iecm_vport *vport, bool add, bool async)
> +{
> +	struct iecm_adapter *adapter = vport->adapter;
> +	struct virtchnl_ether_addr_list *veal = NULL;
> +	int num_entries, num_msgs, total_filters = 0;
> +	struct pci_dev *pdev = adapter->pdev;
> +	enum iecm_vport_vc_state vc, vc_err;
> +	struct virtchnl_ether_addr *eal;
> +	struct iecm_mac_filter *f, *tmp;
> +	int i = 0, k = 0, err = 0;
> +	enum virtchnl_ops vop;
> +
> +	spin_lock_bh(&adapter->mac_filter_list_lock);
> +
> +	/* Find the number of newly added filters */
> +	list_for_each_entry(f, &adapter->config_data.mac_filter_list, list) {
> +		if (add && f->add)
> +			total_filters++;
> +		else if (!add && f->remove)
> +			total_filters++;
> +	}
> +	if (!total_filters) {
> +		spin_unlock_bh(&adapter->mac_filter_list_lock);
> +		goto error;
> +	}
> +
> +	/* Fill all the new filters into virtchannel message */
> +	eal = kcalloc(total_filters, sizeof(struct virtchnl_ether_addr),
> +		      GFP_ATOMIC);
> +	if (!eal) {
> +		err = -ENOMEM;
> +		spin_unlock_bh(&adapter->mac_filter_list_lock);
> +		goto error;
> +	}
> +	list_for_each_entry_safe(f, tmp, &adapter->config_data.mac_filter_list,
> +				 list) {
> +		if (add && f->add) {
> +			ether_addr_copy(eal[i].addr, f->macaddr);
> +			i++;
> +			f->add = false;
> +			if (i == total_filters)
> +				break;
> +		}
> +		if (!add && f->remove) {
> +			ether_addr_copy(eal[i].addr, f->macaddr);
> +			i++;
> +			list_del(&f->list);
> +			kfree(f);
> +			if (i == total_filters)
> +				break;
> +		}
> +	}
> +
> +	spin_unlock_bh(&adapter->mac_filter_list_lock);
> +
> +	/* Chunk up the filters into multiple messages to avoid
> +	 * sending a control queue message buffer that is too large
> +	 */
> +	if (total_filters < IECM_NUM_FILTERS_PER_MSG)
> +		num_entries = total_filters;
> +	else
> +		num_entries = IECM_NUM_FILTERS_PER_MSG;
> +
> +	num_msgs = DIV_ROUND_UP(total_filters, IECM_NUM_FILTERS_PER_MSG);
> +
> +	for (i = 0, k = 0; i < num_msgs || num_entries; i++) {
> +		int buf_size = sizeof(struct virtchnl_ether_addr_list) +
> +			(sizeof(struct virtchnl_ether_addr) * num_entries);
> +		if (!veal || num_entries != IECM_NUM_FILTERS_PER_MSG) {
> +			kfree(veal);
> +			veal = kzalloc(buf_size, GFP_KERNEL);
> +			if (!veal) {
> +				err = -ENOMEM;
> +				goto list_prep_error;
> +			}
> +		} else {
> +			memset(veal, 0, buf_size);
> +		}
> +
> +		veal->vsi_id = vport->vport_id;
> +		veal->num_elements = num_entries;
> +		memcpy(veal->list, &eal[k],
> +		       sizeof(struct virtchnl_ether_addr) * num_entries);
> +
> +		if (add) {
> +			vop = VIRTCHNL_OP_ADD_ETH_ADDR;
> +			vc = IECM_VC_ADD_ETH_ADDR;
> +			vc_err = IECM_VC_ADD_ETH_ADDR_ERR;
> +		} else  {
> +			vop = VIRTCHNL_OP_DEL_ETH_ADDR;
> +			vc = IECM_VC_DEL_ETH_ADDR;
> +			vc_err = IECM_VC_DEL_ETH_ADDR_ERR;
> +		}
> +		err = iecm_send_mb_msg(vport->adapter, vop, buf_size,
> +				       (u8 *)veal);
> +		if (err)
> +			goto mbx_error;
> +
> +		if (!async) {
> +			err = iecm_wait_for_event(vport->adapter, vc, vc_err);
> +			if (err)
> +				goto mbx_error;
> +		}
> +
> +		k += num_entries;
> +		total_filters -= num_entries;
> +		if (total_filters < IECM_NUM_FILTERS_PER_MSG)
> +			num_entries = total_filters;
> +	}
> +mbx_error:
> +	kfree(veal);
> +list_prep_error:
> +	kfree(eal);
> +error:
> +	if (err)
> +		dev_err(&pdev->dev, "Failed to add or del mac filters %d", err);
> +}
> +
>  /**
>   * iecm_add_del_vlans - Add or delete vlan filter
>   * @vport: vport structure
> diff --git a/drivers/net/ethernet/intel/include/iecm.h b/drivers/net/ethernet/intel/include/iecm.h
> index d736db65da06..b5bd73be2855 100644
> --- a/drivers/net/ethernet/intel/include/iecm.h
> +++ b/drivers/net/ethernet/intel/include/iecm.h
> @@ -33,6 +33,11 @@
>  #define IECM_MB_MAX_ERR			20
>  #define IECM_NUM_CHUNKS_PER_MSG(a, b)	((IECM_DFLT_MBX_BUF_SIZE - (a)) / (b))
>  
> +/* 2K is the real maximum, but the driver should not be using more than the
> + * below limit
> + */
> +#define IECM_MAX_VECIDS			256
> +
>  #define IECM_MAX_NUM_VPORTS		1
>  
>  /* available message levels */
> @@ -135,6 +140,10 @@ enum iecm_cap_field {
>  	IECM_CAP_FIELD_LAST,
>  };
>  
> +struct iecm_netdev_priv {
> +	struct iecm_vport *vport;
> +};
> +
>  struct iecm_reset_reg {
>  	u32 rstat;
>  	u32 rstat_m;
> @@ -450,6 +459,8 @@ struct iecm_adapter {
>  	struct msix_entry *msix_entries;
>  	struct virtchnl2_alloc_vectors *req_vec_chunks;
>  	struct iecm_q_vector mb_vector;
> +	/* handler for hard interrupt for mailbox*/
> +	irqreturn_t (*irq_mb_handler)(int irq, void *data);
>  
>  	/* vport structs */
>  	struct iecm_vport **vports;	/* vports created by the driver */
> @@ -537,12 +548,88 @@ static inline bool __iecm_is_cap_ena(struct iecm_adapter *adapter, bool all,
>  	return adapter->dev_ops.vc_ops.is_cap_ena(adapter, all, field, flag);
>  }
>  
> -#define IECM_CAP_HSPLIT (\
> -	VIRTCHNL2_CAP_RX_HSPLIT_AT_L2   |\
> -	VIRTCHNL2_CAP_RX_HSPLIT_AT_L3   |\
> -	VIRTCHNL2_CAP_RX_HSPLIT_AT_L4V4 |\
> +/* enum used to distinguish vlan capabilities */
> +enum iecm_vlan_caps {
> +	IECM_CAP_VLAN_CTAG_INSERT,
> +	IECM_CAP_VLAN_STAG_INSERT,
> +	IECM_CAP_VLAN_CTAG_STRIP,
> +	IECM_CAP_VLAN_STAG_STRIP,
> +	IECM_CAP_VLAN_CTAG_ADD_DEL,
> +	IECM_CAP_VLAN_STAG_ADD_DEL,
> +	IECM_CAP_VLAN_LAST,
> +};
> +
> +#define IECM_VLAN_8100 (VIRTCHNL_VLAN_TOGGLE | VIRTCHNL_VLAN_ETHERTYPE_8100)
> +#define IECM_VLAN_88A8 (VIRTCHNL_VLAN_TOGGLE | VIRTCHNL_VLAN_ETHERTYPE_88A8)
> +
> +#define IECM_F_HW_VLAN_CTAG_TX NETIF_F_HW_VLAN_CTAG_TX
> +
> +#define IECM_F_HW_VLAN_CTAG_RX NETIF_F_HW_VLAN_CTAG_RX
> +
> +#define IECM_F_HW_VLAN_CTAG_FILTER NETIF_F_HW_VLAN_CTAG_FILTER
> +
> +#define IECM_CAP_RSS (\
> +	VIRTCHNL2_CAP_RSS_IPV4_TCP	|\
> +	VIRTCHNL2_CAP_RSS_IPV4_TCP	|\
> +	VIRTCHNL2_CAP_RSS_IPV4_UDP	|\
> +	VIRTCHNL2_CAP_RSS_IPV4_SCTP	|\
> +	VIRTCHNL2_CAP_RSS_IPV4_OTHER	|\
> +	VIRTCHNL2_CAP_RSS_IPV4_AH	|\
> +	VIRTCHNL2_CAP_RSS_IPV4_ESP	|\
> +	VIRTCHNL2_CAP_RSS_IPV4_AH_ESP	|\
> +	VIRTCHNL2_CAP_RSS_IPV6_TCP	|\
> +	VIRTCHNL2_CAP_RSS_IPV6_TCP	|\
> +	VIRTCHNL2_CAP_RSS_IPV6_UDP	|\
> +	VIRTCHNL2_CAP_RSS_IPV6_SCTP	|\
> +	VIRTCHNL2_CAP_RSS_IPV6_OTHER	|\
> +	VIRTCHNL2_CAP_RSS_IPV6_AH	|\
> +	VIRTCHNL2_CAP_RSS_IPV6_ESP	|\
> +	VIRTCHNL2_CAP_RSS_IPV6_AH_ESP)
> +
> +#define IECM_CAP_RSC (\
> +	VIRTCHNL2_CAP_RSC_IPV4_TCP	|\
> +	VIRTCHNL2_CAP_RSC_IPV4_SCTP	|\
> +	VIRTCHNL2_CAP_RSC_IPV6_TCP	|\
> +	VIRTCHNL2_CAP_RSC_IPV6_SCTP)
> +
> +#define IECM_CAP_HSPLIT	(\
> +	VIRTCHNL2_CAP_RX_HSPLIT_AT_L2	|\
> +	VIRTCHNL2_CAP_RX_HSPLIT_AT_L3	|\
> +	VIRTCHNL2_CAP_RX_HSPLIT_AT_L4V4	|\
>  	VIRTCHNL2_CAP_RX_HSPLIT_AT_L4V6)
>  
> +#define IECM_CAP_RX_CSUM_L4V4 (\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_TCP	|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_UDP)
> +
> +#define IECM_CAP_RX_CSUM_L4V6 (\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_TCP	|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_UDP)
> +
> +#define IECM_CAP_RX_CSUM (\
> +	VIRTCHNL2_CAP_RX_CSUM_L3_IPV4		|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_TCP	|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_UDP	|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_SCTP	|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_TCP	|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_UDP	|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_SCTP)
> +
> +#define IECM_CAP_SCTP_CSUM (\
> +	VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_SCTP	|\
> +	VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_SCTP	|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_SCTP	|\
> +	VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_SCTP)
> +
> +/**
> + * iecm_get_reserved_vecs - Get reserved vectors
> + * @adapter: private data struct
> + */
> +static inline u16 iecm_get_reserved_vecs(struct iecm_adapter *adapter)
> +{
> +	return adapter->dev_ops.vc_ops.get_reserved_vecs(adapter);
> +}
> +
>  /**
>   * iecm_is_reset_detected - check if we were reset at some point
>   * @adapter: driver specific private structure
> @@ -555,6 +642,20 @@ static inline bool iecm_is_reset_detected(struct iecm_adapter *adapter)
>  		 adapter->hw.arq->reg.len_ena_mask);
>  }
>  
> +/**
> + * iecm_is_reset_in_prog - check if reset is in progress
> + * @adapter: driver specific private structure
> + *
> + * Returns true if hard reset is in progress, false otherwise
> + */
> +static inline bool iecm_is_reset_in_prog(struct iecm_adapter *adapter)
> +{
> +	return (test_bit(__IECM_HR_RESET_IN_PROG, adapter->flags) ||
> +		test_bit(__IECM_HR_FUNC_RESET, adapter->flags) ||
> +		test_bit(__IECM_HR_CORE_RESET, adapter->flags) ||
> +		test_bit(__IECM_HR_DRV_LOAD, adapter->flags));
> +}
> +
>  int iecm_probe(struct pci_dev *pdev,
>  	       const struct pci_device_id __always_unused *ent,
>  	       struct iecm_adapter *adapter);
> @@ -576,6 +677,7 @@ int iecm_send_get_caps_msg(struct iecm_adapter *adapter);
>  int iecm_send_delete_queues_msg(struct iecm_vport *vport);
>  int iecm_send_add_queues_msg(struct iecm_vport *vport, u16 num_tx_q,
>  			     u16 num_complq, u16 num_rx_q, u16 num_rx_bufq);
> +int iecm_send_vlan_v2_caps_msg(struct iecm_adapter *adapter);
>  int iecm_send_config_tx_queues_msg(struct iecm_vport *vport);
>  int iecm_send_config_rx_queues_msg(struct iecm_vport *vport);
>  int iecm_send_enable_vport_msg(struct iecm_vport *vport);
> @@ -589,6 +691,7 @@ int iecm_send_dealloc_vectors_msg(struct iecm_adapter *adapter);
>  int iecm_send_alloc_vectors_msg(struct iecm_adapter *adapter, u16 num_vectors);
>  int iecm_vport_params_buf_alloc(struct iecm_adapter *adapter);
>  void iecm_vport_params_buf_rel(struct iecm_adapter *adapter);
> +struct iecm_vport *iecm_netdev_to_vport(struct net_device *netdev);
>  int iecm_send_get_stats_msg(struct iecm_vport *vport);
>  int iecm_get_vec_ids(struct iecm_adapter *adapter,
>  		     u16 *vecids, int num_vecids,
> @@ -598,6 +701,7 @@ int iecm_recv_mb_msg(struct iecm_adapter *adapter, enum virtchnl_ops op,
>  int iecm_send_mb_msg(struct iecm_adapter *adapter, enum virtchnl_ops op,
>  		     u16 msg_size, u8 *msg);
>  void iecm_vport_set_hsplit(struct iecm_vport *vport, bool ena);
> +void iecm_add_del_ether_addrs(struct iecm_vport *vport, bool add, bool async);
>  int iecm_send_enable_channels_msg(struct iecm_vport *vport);
>  int iecm_send_disable_channels_msg(struct iecm_vport *vport);
>  bool iecm_is_feature_ena(struct iecm_vport *vport, netdev_features_t feature);
> diff --git a/drivers/net/ethernet/intel/include/iecm_txrx.h b/drivers/net/ethernet/intel/include/iecm_txrx.h
> index 9f3086bfe575..0aa1eac70e7c 100644
> --- a/drivers/net/ethernet/intel/include/iecm_txrx.h
> +++ b/drivers/net/ethernet/intel/include/iecm_txrx.h
> @@ -512,4 +512,6 @@ void iecm_vport_calc_total_qs(struct iecm_adapter *adapter,
>  			      struct virtchnl2_create_vport *vport_msg);
>  void iecm_vport_calc_num_q_groups(struct iecm_vport *vport);
>  void iecm_vport_calc_num_q_vec(struct iecm_vport *vport);
> +irqreturn_t
> +iecm_vport_intr_clean_queues(int __always_unused irq, void *data);
>  #endif /* !_IECM_TXRX_H_ */
> -- 
> 2.33.0

Thanks,
Al


  reply	other threads:[~2022-01-28 13:34 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-28  0:09 [Intel-wired-lan] [PATCH net-next 00/19] Add iecm and idpf Alan Brady
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 01/19] virtchnl: Add new virtchnl2 ops Alan Brady
2022-02-02 22:13   ` Brady, Alan
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 02/19] iecm: add basic module init and documentation Alan Brady
2022-01-28 11:56   ` Alexander Lobakin
2022-02-02 22:15     ` Brady, Alan
2022-02-01 19:44   ` Shannon Nelson
2022-02-03  3:08     ` Brady, Alan
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 03/19] iecm: add probe and remove Alan Brady
2022-02-01 20:02   ` Shannon Nelson
2022-02-03  3:13     ` Brady, Alan
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 04/19] iecm: add api_init and controlq init Alan Brady
2022-01-28 12:09   ` Alexander Lobakin
2022-02-02 22:16     ` Brady, Alan
2022-02-01 21:26   ` Shannon Nelson
2022-02-03  3:24     ` Brady, Alan
2022-02-03  3:40       ` Brady, Alan
2022-02-03  5:26         ` Shannon Nelson
2022-02-03 13:13       ` Alexander Lobakin
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 05/19] iecm: add vport alloc and virtchnl messages Alan Brady
2022-01-28  4:19   ` kernel test robot
2022-01-28 12:39     ` Alexander Lobakin
2022-02-02 22:23       ` Brady, Alan
2022-01-28 12:32   ` Alexander Lobakin
2022-02-02 22:21     ` Brady, Alan
2022-02-03 13:23       ` Alexander Lobakin
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 06/19] iecm: add virtchnl messages for queues Alan Brady
2022-01-28 13:03   ` Alexander Lobakin
2022-02-02 22:48     ` Brady, Alan
2022-02-03 10:08       ` Maciej Fijalkowski
2022-02-03 14:09       ` Alexander Lobakin
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 07/19] iecm: finish virtchnl messages Alan Brady
2022-01-28 13:19   ` Alexander Lobakin
2022-02-02 23:06     ` Brady, Alan
2022-02-03 15:05       ` Alexander Lobakin
2022-02-03 15:16         ` Maciej Fijalkowski
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 08/19] iecm: add interrupts and configure netdev Alan Brady
2022-01-28 13:34   ` Alexander Lobakin [this message]
2022-02-02 23:17     ` Brady, Alan
2022-02-03 15:55       ` Alexander Lobakin
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 09/19] iecm: alloc vport TX resources Alan Brady
2022-02-02 23:45   ` Brady, Alan
2022-02-03 17:56     ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 10/19] iecm: alloc vport RX resources Alan Brady
2022-01-28 14:16   ` Alexander Lobakin
2022-02-03  0:13     ` Brady, Alan
2022-02-03 18:29       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 11/19] iecm: add start_xmit and set_rx_mode Alan Brady
2022-01-28 16:35   ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 12/19] iecm: finish netdev_ops Alan Brady
2022-01-28 17:06   ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 13/19] iecm: implement splitq napi_poll Alan Brady
2022-01-28  5:21   ` kernel test robot
2022-01-28 17:44     ` Alexander Lobakin
2022-02-03  1:15       ` Brady, Alan
2022-01-28 17:38   ` Alexander Lobakin
2022-02-03  1:07     ` Brady, Alan
2022-02-04 11:50       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 14/19] iecm: implement singleq napi_poll Alan Brady
2022-01-28 17:57   ` Alexander Lobakin
2022-02-03  1:45     ` Brady, Alan
2022-02-03 19:05       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 15/19] iecm: implement ethtool callbacks Alan Brady
2022-01-28 18:13   ` Alexander Lobakin
2022-02-03  2:13     ` Brady, Alan
2022-02-03 19:54       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 16/19] iecm: implement flow director Alan Brady
2022-01-28 19:04   ` Alexander Lobakin
2022-02-03  2:41     ` Brady, Alan
2022-02-04 10:08       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 17/19] iecm: implement cloud filters Alan Brady
2022-01-28 19:38   ` Alexander Lobakin
2022-02-03  2:53     ` Brady, Alan
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 18/19] iecm: add advanced rss Alan Brady
2022-01-28 19:53   ` Alexander Lobakin
2022-02-03  2:55     ` Brady, Alan
2022-02-03 10:46       ` Maciej Fijalkowski
2022-02-04 10:22       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 19/19] idpf: introduce idpf driver Alan Brady
2022-01-28 20:08   ` Alexander Lobakin
2022-02-03  3:07     ` Brady, Alan
2022-02-04 10:35       ` Alexander Lobakin
2022-02-04 12:05 ` [Intel-wired-lan] [PATCH net-next 00/19] Add iecm and idpf Alexander Lobakin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220128133447.22242-1-alexandr.lobakin@intel.com \
    --to=alexandr.lobakin@intel.com \
    --cc=intel-wired-lan@osuosl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox