All of 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: 89+ 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  4:19     ` kernel test robot
2022-01-28 12:39     ` Alexander Lobakin
2022-01-28 12:39       ` Alexander Lobakin
2022-02-02 22:23       ` Brady, Alan
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  5:21     ` kernel test robot
2022-01-28 17:44     ` Alexander Lobakin
2022-01-28 17:44       ` Alexander Lobakin
2022-02-03  1:15       ` Brady, Alan
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.