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 05/19] iecm: add vport alloc and virtchnl messages
Date: Fri, 28 Jan 2022 13:32:44 +0100	[thread overview]
Message-ID: <20220128123244.21159-1-alexandr.lobakin@intel.com> (raw)
In-Reply-To: <20220128001009.721392-6-alan.brady@intel.com>

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

> After handling hard reset, we end up in init task. This starts by
> allocating and setting up a vport. To do that we need implement virtchnl
> messages.
> 
> The virtchnl messages are also offloaded into function pointers so that a
> device driver may override them. Here a default implementation is provided
> for devices using virtchnl 2.0 but there exists the flexibility add
> virtchnl 1.1 support through function pointers.
> 
> 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: Alan Brady <alan.brady@intel.com>
> ---
>  drivers/net/ethernet/intel/iecm/Makefile      |    4 +-
>  drivers/net/ethernet/intel/iecm/iecm_lib.c    |  167 ++-
>  drivers/net/ethernet/intel/iecm/iecm_txrx.c   |   22 +
>  .../net/ethernet/intel/iecm/iecm_virtchnl.c   | 1299 +++++++++++++++++
>  drivers/net/ethernet/intel/include/iecm.h     |  316 +++-
>  .../net/ethernet/intel/include/iecm_txrx.h    |   94 ++
>  6 files changed, 1898 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/net/ethernet/intel/iecm/iecm_txrx.c
> 
> diff --git a/drivers/net/ethernet/intel/iecm/Makefile b/drivers/net/ethernet/intel/iecm/Makefile
> index db8fecb075a6..fcb49402334f 100644
> --- a/drivers/net/ethernet/intel/iecm/Makefile
> +++ b/drivers/net/ethernet/intel/iecm/Makefile
> @@ -7,11 +7,13 @@
>  
>  obj-$(CONFIG_IECM) += iecm.o
>  
> -ccflags-y += -I$(srctree)/drivers/net/ethernet/intel/include
> +ccflags-y += -I$(srctree)/drivers/net/ethernet/intel/include \
> +	     -I$(srctree)/include/linux/avf
>  
>  iecm-y := \
>  	iecm_lib.o \
>  	iecm_virtchnl.o \
> +	iecm_txrx.o \
>  	iecm_controlq.o \
>  	iecm_controlq_setup.o \
>  	iecm_main.o
> diff --git a/drivers/net/ethernet/intel/iecm/iecm_lib.c b/drivers/net/ethernet/intel/iecm/iecm_lib.c
> index 64cdbce2c842..e2e523f0700e 100644
> --- a/drivers/net/ethernet/intel/iecm/iecm_lib.c
> +++ b/drivers/net/ethernet/intel/iecm/iecm_lib.c
> @@ -5,6 +5,11 @@
>  
>  #include "iecm.h"
>  
> +const char * const iecm_vport_vc_state_str[] = {
> +	IECM_FOREACH_VPORT_VC_STATE(IECM_GEN_STRING)
> +};
> +EXPORT_SYMBOL(iecm_vport_vc_state_str);
> +
>  /**
>   * iecm_cfg_hw - Initialize HW struct
>   * @adapter: adapter to setup hw struct for
> @@ -24,6 +29,113 @@ static int iecm_cfg_hw(struct iecm_adapter *adapter)
>  	return 0;
>  }
>  
> +/**
> + * iecm_get_free_slot - get the next non-NULL location index in array
> + * @array: array to search
> + * @size: size of the array
> + * @curr: last known occupied index to be used as a search hint
> + *
> + * void * is being used to keep the functionality generic. This lets us use this
> + * function on any array of pointers.
> + */
> +static int iecm_get_free_slot(void *array, int size, int curr)
> +{
> +	int **tmp_array = (int **)array;
> +	int next;
> +
> +	if (curr < (size - 1) && !tmp_array[curr + 1]) {

Redundant braces around `size - 1`.

> +		next = curr + 1;
> +	} else {
> +		int i = 0;
> +
> +		while ((i < size) && (tmp_array[i]))
> +			i++;
> +		if (i == size)
> +			next = IECM_NO_FREE_SLOT;
> +		else
> +			next = i;
> +	}

One indent level is redundant here. First condition is an oneliner:

	if (curr < (size - 1) && !tmp_array[curr + 1]) {
		return curr + 1;

	while ((i < size) && (tmp_array[i])) {
		...

> +	return next;
> +}
> +
> +/**
> + * iecm_vport_rel - Delete a vport and free its resources
> + * @vport: the vport being removed
> + */
> +static void iecm_vport_rel(struct iecm_vport *vport)
> +{
> +	mutex_destroy(&vport->stop_mutex);
> +	kfree(vport);
> +}
> +
> +/**
> + * iecm_vport_rel_all - Delete all vports
> + * @adapter: adapter from which all vports are being removed
> + */
> +static void iecm_vport_rel_all(struct iecm_adapter *adapter)
> +{
> +	int i;
> +
> +	if (!adapter->vports)
> +		return;
> +
> +	for (i = 0; i < adapter->num_alloc_vport; i++) {
> +		if (!adapter->vports[i])
> +			continue;
> +
> +		iecm_vport_rel(adapter->vports[i]);
> +		adapter->vports[i] = NULL;
> +		adapter->next_vport = 0;
> +	}
> +	adapter->num_alloc_vport = 0;
> +}
> +
> +/**
> + * iecm_vport_alloc - Allocates the next available struct vport in the adapter
> + * @adapter: board private structure
> + * @vport_id: vport identifier
> + *
> + * returns a pointer to a vport on success, NULL on failure.
> + */
> +static struct iecm_vport *
> +iecm_vport_alloc(struct iecm_adapter *adapter, int vport_id)
> +{
> +	struct iecm_vport *vport = NULL;
> +
> +	if (adapter->next_vport == IECM_NO_FREE_SLOT)
> +		return vport;
> +
> +	/* Need to protect the allocation of the vports at the adapter level */
> +	mutex_lock(&adapter->sw_mutex);
> +
> +	vport = kzalloc(sizeof(*vport), GFP_KERNEL);
> +	if (!vport)
> +		goto unlock_adapter;
> +
> +	vport->adapter = adapter;
> +	vport->idx = adapter->next_vport;
> +	vport->compln_clean_budget = IECM_TX_COMPLQ_CLEAN_BUDGET;
> +	adapter->num_alloc_vport++;
> +
> +	/* Setup default MSIX irq handler for the vport */
> +	vport->irq_q_handler = iecm_vport_intr_clean_queues;
> +	vport->q_vector_base = IECM_NONQ_VEC;
> +
> +	mutex_init(&vport->stop_mutex);
> +
> +	/* fill vport slot in the adapter struct */
> +	adapter->vports[adapter->next_vport] = vport;
> +
> +	/* prepare adapter->next_vport for next use */
> +	adapter->next_vport = iecm_get_free_slot(adapter->vports,
> +						 adapter->num_alloc_vport,
> +						 adapter->next_vport);
> +
> +unlock_adapter:
> +	mutex_unlock(&adapter->sw_mutex);
> +	return vport;
> +}
> +
>  /**
>   * iecm_statistics_task - Delayed task to get statistics over mailbox
>   * @work: work_struct handle to our data
> @@ -55,7 +167,25 @@ static void iecm_service_task(struct work_struct *work)
>   */
>  static void iecm_init_task(struct work_struct *work)
>  {
> -	/* stub */
> +	struct iecm_adapter *adapter = container_of(work,
> +						    struct iecm_adapter,
> +						    init_task.work);
> +	struct iecm_vport *vport;
> +	struct pci_dev *pdev;
> +	int vport_id, err;
> +
> +	err = adapter->dev_ops.vc_ops.core_init(adapter, &vport_id);
> +	if (err)
> +		return;
> +
> +	pdev = adapter->pdev;
> +	vport = iecm_vport_alloc(adapter, vport_id);
> +	if (!vport) {
> +		err = -EFAULT;
> +		dev_err(&pdev->dev, "failed to allocate vport: %d\n",
> +			err);
> +		return;
> +	}
>  }
>  
>  /**
> @@ -81,6 +211,31 @@ static int iecm_api_init(struct iecm_adapter *adapter)
>  		return -EINVAL;
>  	}
>  
> +	if (adapter->dev_ops.vc_ops_init) {
> +		struct iecm_virtchnl_ops *vc_ops;
> +
> +		adapter->dev_ops.vc_ops_init(adapter);
> +		vc_ops = &adapter->dev_ops.vc_ops;
> +		if (!(vc_ops->core_init &&
> +		      vc_ops->vport_init &&
> +		      vc_ops->vport_queue_ids_init &&
> +		      vc_ops->get_caps &&
> +		      vc_ops->config_queues &&
> +		      vc_ops->enable_queues &&
> +		      vc_ops->disable_queues &&
> +		      vc_ops->irq_map_unmap &&
> +		      vc_ops->get_set_rss_lut &&
> +		      vc_ops->get_set_rss_hash &&
> +		      vc_ops->adjust_qs &&
> +		      vc_ops->get_ptype &&
> +		      vc_ops->init_max_queues)) {

if (!op1 ||
    !op2 ||
    !opn) would look more natural and more readable here.

> +			dev_err(&pdev->dev, "Invalid device, missing one or more virtchnl functions\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		iecm_vc_ops_init(adapter);
> +	}

'else' path is a two-liner allowing to save one indent level:

	if (!adapter->dev_ops.vc_ops_init) {
		iecm_vc_ops_init(adapter);
		return 0;
	}

	adapter->dev_ops.vc_ops_init(adapter);
	vc_ops = &adapter->dev_ops.vc_ops;
	if (!(vc_ops->core_init &&
	...

> +
>  	return 0;
>  }
>  
> @@ -93,7 +248,15 @@ static int iecm_api_init(struct iecm_adapter *adapter)
>   */
>  static void iecm_deinit_task(struct iecm_adapter *adapter)
>  {
> -	/* stub */
> +	set_bit(__IECM_REL_RES_IN_PROG, adapter->flags);
> +	/* Wait until the init_task is done else this thread might release
> +	 * the resources first and the other thread might end up in a bad state
> +	 */
> +	cancel_delayed_work_sync(&adapter->init_task);
> +	iecm_vport_rel_all(adapter);
> +
> +	cancel_delayed_work_sync(&adapter->serv_task);
> +	cancel_delayed_work_sync(&adapter->stats_task);
>  }
>  
>  /**
> diff --git a/drivers/net/ethernet/intel/iecm/iecm_txrx.c b/drivers/net/ethernet/intel/iecm/iecm_txrx.c
> new file mode 100644
> index 000000000000..2f5c16a28266
> --- /dev/null
> +++ b/drivers/net/ethernet/intel/iecm/iecm_txrx.c
> @@ -0,0 +1,22 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (C) 2019 Intel Corporation */
> +
> +#include "iecm.h"
> +
> +/**
> + * 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;
> +}
> +
> diff --git a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
> index b8f54b8c700a..aae06064d706 100644
> --- a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
> +++ b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
> @@ -3,6 +3,74 @@
>  
>  #include "iecm.h"
>  
> +/**
> + * iecm_recv_event_msg - Receive virtchnl event message
> + * @vport: virtual port structure
> + *
> + * Receive virtchnl event message
> + */
> +static void iecm_recv_event_msg(struct iecm_vport *vport)
> +{
> +	struct iecm_adapter *adapter = vport->adapter;
> +	struct virtchnl_pf_event *vpe;
> +	struct virtchnl2_event *v2e;
> +	bool link_status;
> +	u32 event;
> +
> +	if (adapter->virt_ver_maj < VIRTCHNL_VERSION_MAJOR_2) {
> +		vpe = (struct virtchnl_pf_event *)adapter->vc_msg;
> +		event = vpe->event;
> +	} else {
> +		v2e = (struct virtchnl2_event *)adapter->vc_msg;
> +		event = le32_to_cpu(v2e->event);
> +	}
> +
> +	switch (event) {
> +	case VIRTCHNL2_EVENT_LINK_CHANGE:
> +		if (adapter->virt_ver_maj < VIRTCHNL_VERSION_MAJOR_2) {
> +			if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS,
> +					    VIRTCHNL2_CAP_LINK_SPEED)) {
> +				adapter->link_speed_mbps =
> +				vpe->event_data.link_event_adv.link_speed;
> +				link_status =
> +				vpe->event_data.link_event_adv.link_status;
> +			} else {
> +				adapter->link_speed =
> +				vpe->event_data.link_event.link_speed;
> +				link_status =
> +				vpe->event_data.link_event.link_status;
> +			}
> +		} else {
> +			adapter->link_speed_mbps = le32_to_cpu(v2e->link_speed);
> +			link_status = v2e->link_status;
> +		}
> +		if (adapter->link_up != link_status) {
> +			adapter->link_up = link_status;
> +			if (adapter->state == __IECM_UP) {
> +				if (adapter->link_up) {
> +					netif_tx_start_all_queues(vport->netdev);
> +					netif_carrier_on(vport->netdev);
> +				} else {
> +					netif_tx_stop_all_queues(vport->netdev);
> +					netif_carrier_off(vport->netdev);
> +				}
> +			}
> +		}
> +		break;
> +	case VIRTCHNL_EVENT_RESET_IMPENDING:
> +		set_bit(__IECM_HR_CORE_RESET, adapter->flags);
> +		queue_delayed_work(adapter->vc_event_wq,
> +				   &adapter->vc_event_task,
> +				   msecs_to_jiffies(10));
> +		break;
> +	default:
> +		dev_err(&vport->adapter->pdev->dev,
> +			"Unknown event %d from PF\n", event);
> +		break;
> +	}
> +	clear_bit(__IECM_VC_MSG_PENDING, adapter->flags);
> +}
> +
>  /**
>   * iecm_mb_clean - Reclaim the send mailbox queue entries
>   * @adapter: Driver specific private structure
> @@ -39,6 +107,865 @@ static int iecm_mb_clean(struct iecm_adapter *adapter)
>  	return err;
>  }
>  
> +/**
> + * iecm_send_mb_msg - Send message over mailbox
> + * @adapter: Driver specific private structure
> + * @op: virtchnl opcode
> + * @msg_size: size of the payload
> + * @msg: pointer to buffer holding the payload
> + *
> + * Will prepare the control queue message and initiates the send api
> + *
> + * Returns 0 on success, negative on failure
> + */
> +int iecm_send_mb_msg(struct iecm_adapter *adapter, enum virtchnl_ops op,
> +		     u16 msg_size, u8 *msg)
> +{
> +	struct iecm_ctlq_msg *ctlq_msg;
> +	struct iecm_dma_mem *dma_mem;
> +	int err = 0;
> +
> +	if (iecm_is_reset_detected(adapter))
> +		return -EBUSY;
> +
> +	err = iecm_mb_clean(adapter);
> +	if (err)
> +		return err;
> +
> +	ctlq_msg = kzalloc(sizeof(*ctlq_msg), GFP_KERNEL);
> +	if (!ctlq_msg)
> +		return -ENOMEM;
> +
> +	dma_mem = kzalloc(sizeof(*dma_mem), GFP_KERNEL);
> +	if (!dma_mem) {
> +		err = -ENOMEM;
> +		goto dma_mem_error;
> +	}
> +
> +	memset(ctlq_msg, 0, sizeof(struct iecm_ctlq_msg));
> +	ctlq_msg->opcode = iecm_mbq_opc_send_msg_to_pf;
> +	ctlq_msg->func_id = 0;
> +	ctlq_msg->data_len = msg_size;
> +	ctlq_msg->cookie.mbx.chnl_opcode = op;
> +	ctlq_msg->cookie.mbx.chnl_retval = VIRTCHNL_STATUS_SUCCESS;
> +	dma_mem->size = IECM_DFLT_MBX_BUF_SIZE;
> +	dma_mem->va = dmam_alloc_coherent(&adapter->pdev->dev, dma_mem->size,
> +					  &dma_mem->pa, GFP_KERNEL);
> +	if (!dma_mem->va) {
> +		err = -ENOMEM;
> +		goto dma_alloc_error;
> +	}
> +	memcpy(dma_mem->va, msg, msg_size);
> +	ctlq_msg->ctx.indirect.payload = dma_mem;
> +
> +	err = iecm_ctlq_send(&adapter->hw, adapter->hw.asq, 1, ctlq_msg);
> +	if (err)
> +		goto send_error;
> +
> +	return 0;
> +send_error:
> +	dmam_free_coherent(&adapter->pdev->dev, dma_mem->size, dma_mem->va,
> +			   dma_mem->pa);
> +dma_alloc_error:
> +	kfree(dma_mem);
> +dma_mem_error:
> +	kfree(ctlq_msg);
> +	return err;
> +}
> +EXPORT_SYMBOL(iecm_send_mb_msg);
> +
> +/**
> + * iecm_set_msg_pending_bit - Wait for clear and set msg pending
> + * @adapter: driver specific private structure
> + *
> + * If clear sets msg pending bit, otherwise waits for it to clear before
> + * setting it again. Returns 0 on success, negative on failure.
> + */
> +static int iecm_set_msg_pending_bit(struct iecm_adapter *adapter)
> +{
> +	unsigned int retries = 100;
> +
> +	/* If msg pending bit already set, there's a message waiting to be
> +	 * parsed and we must wait for it to be cleared before copying a new
> +	 * message into the vc_msg buffer or else we'll stomp all over the
> +	 * previous message.
> +	 */
> +	while (retries) {
> +		if (!test_and_set_bit(__IECM_VC_MSG_PENDING,
> +				      adapter->flags))
> +			break;
> +		msleep(20);
> +		retries--;
> +	}
> +	return retries ? 0 : -ETIMEDOUT;
> +}
> +
> +/**
> + * iecm_set_msg_pending - Wait for msg pending bit and copy msg to buf
> + * @adapter: driver specific private structure
> + * @ctlq_msg: msg to copy from
> + * @err_enum: err bit to set on error
> + *
> + * Copies payload from ctlq_msg into vc_msg buf in adapter and sets msg pending
> + * bit. Returns 0 on success, negative on failure.
> + */
> +int iecm_set_msg_pending(struct iecm_adapter *adapter,
> +			 struct iecm_ctlq_msg *ctlq_msg,
> +			 enum iecm_vport_vc_state err_enum)
> +{
> +	if (ctlq_msg->cookie.mbx.chnl_retval) {
> +		set_bit(err_enum, adapter->vc_state);
> +		return -EINVAL;
> +	}
> +
> +	if (iecm_set_msg_pending_bit(adapter)) {
> +		set_bit(err_enum, adapter->vc_state);
> +		dev_info(&adapter->pdev->dev, "Timed out setting msg pending\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	memcpy(adapter->vc_msg, ctlq_msg->ctx.indirect.payload->va,
> +	       min_t(int, ctlq_msg->ctx.indirect.payload->size,
> +		     IECM_DFLT_MBX_BUF_SIZE));
> +	return 0;
> +}
> +EXPORT_SYMBOL(iecm_set_msg_pending);
> +
> +/**
> + * iecm_recv_mb_msg - Receive message over mailbox
> + * @adapter: Driver specific private structure
> + * @op: virtchannel operation code
> + * @msg: Received message holding buffer
> + * @msg_size: message size
> + *
> + * Will receive control queue message and posts the receive buffer. Returns 0
> + * on success and negative on failure.
> + */
> +int iecm_recv_mb_msg(struct iecm_adapter *adapter, enum virtchnl_ops op,
> +		     void *msg, int msg_size)
> +{
> +	struct iecm_ctlq_msg ctlq_msg;
> +	struct iecm_dma_mem *dma_mem;
> +	struct iecm_vport *vport;
> +	bool work_done = false;
> +	int num_retry = 2000;
> +	int payload_size = 0;
> +	u16 num_q_msg;
> +	int err = 0;
> +
> +	vport = adapter->vports[0];
> +	while (1) {
> +		/* Try to get one message */
> +		num_q_msg = 1;
> +		dma_mem = NULL;
> +		err = iecm_ctlq_recv(adapter->hw.arq, &num_q_msg, &ctlq_msg);
> +		/* If no message then decide if we have to retry based on
> +		 * opcode
> +		 */
> +		if (err || !num_q_msg) {
> +			/* Increasing num_retry to consider the delayed
> +			 * responses because of large number of VF's mailbox
> +			 * messages. If the mailbox message is received from
> +			 * the other side, we come out of the sleep cycle
> +			 * immediately else we wait for more time.
> +			 */
> +			if (op && num_retry-- &&
> +			    !test_bit(__IECM_REL_RES_IN_PROG, adapter->flags)) {
> +				msleep(20);
> +				continue;
> +			} else {
> +				break;
> +			}

Since if-condition always ends with a 'continue', 'else' is
reduntant here.

> +		}
> +
> +		/* If we are here a message is received. Check if we are looking
> +		 * for a specific message based on opcode. If it is different
> +		 * ignore and post buffers
> +		 */
> +		if (op && ctlq_msg.cookie.mbx.chnl_opcode != op)
> +			goto post_buffs;
> +
> +		if (ctlq_msg.data_len)
> +			payload_size = ctlq_msg.ctx.indirect.payload->size;
> +
> +		/* All conditions are met. Either a message requested is
> +		 * received or we received a message to be processed
> +		 */
> +		switch (ctlq_msg.cookie.mbx.chnl_opcode) {
> +		case VIRTCHNL_OP_VERSION:
> +		case VIRTCHNL2_OP_GET_CAPS:
> +		case VIRTCHNL2_OP_CREATE_VPORT:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_info(&adapter->pdev->dev, "Failure initializing, vc op: %u retval: %u\n",
> +					 ctlq_msg.cookie.mbx.chnl_opcode,
> +					 ctlq_msg.cookie.mbx.chnl_retval);
> +				err = -EBADMSG;
> +			} else if (msg) {
> +				memcpy(msg, ctlq_msg.ctx.indirect.payload->va,
> +				       min_t(int,
> +					     payload_size, msg_size));
> +			}
> +			work_done = true;
> +			break;
> +		case VIRTCHNL2_OP_ENABLE_VPORT:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_ENA_VPORT_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_ENA_VPORT, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_DISABLE_VPORT:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_DIS_VPORT_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_DIS_VPORT, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_DESTROY_VPORT:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_DESTROY_VPORT_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_DESTROY_VPORT, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_CONFIG_TX_QUEUES:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_CONFIG_TXQ_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_CONFIG_TXQ, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_CONFIG_RX_QUEUES:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_CONFIG_RXQ_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_CONFIG_RXQ, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_ENABLE_QUEUES:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_ENA_QUEUES_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_ENA_QUEUES, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_DISABLE_QUEUES:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_DIS_QUEUES_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_DIS_QUEUES, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_ADD_QUEUES:
> +			iecm_set_msg_pending(adapter, &ctlq_msg,
> +					     IECM_VC_ADD_QUEUES_ERR);
> +			set_bit(IECM_VC_ADD_QUEUES, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_DEL_QUEUES:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_DEL_QUEUES_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_DEL_QUEUES, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_MAP_QUEUE_VECTOR:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_MAP_IRQ_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_MAP_IRQ, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_UNMAP_QUEUE_VECTOR:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_UNMAP_IRQ_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_UNMAP_IRQ, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_GET_STATS:
> +			iecm_set_msg_pending(adapter, &ctlq_msg,
> +					     IECM_VC_GET_STATS_ERR);
> +			set_bit(IECM_VC_GET_STATS, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_GET_RSS_HASH:
> +			iecm_set_msg_pending(adapter, &ctlq_msg,
> +					     IECM_VC_GET_RSS_HASH_ERR);
> +			set_bit(IECM_VC_GET_RSS_HASH, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_SET_RSS_HASH:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_SET_RSS_HASH_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_SET_RSS_HASH, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_GET_RSS_LUT:
> +			iecm_set_msg_pending(adapter, &ctlq_msg,
> +					     IECM_VC_GET_RSS_LUT_ERR);
> +			set_bit(IECM_VC_GET_RSS_LUT, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_SET_RSS_LUT:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_SET_RSS_LUT_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_SET_RSS_LUT, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_GET_RSS_KEY:
> +			iecm_set_msg_pending(adapter, &ctlq_msg,
> +					     IECM_VC_GET_RSS_KEY_ERR);
> +			set_bit(IECM_VC_GET_RSS_KEY, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_SET_RSS_KEY:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_SET_RSS_KEY_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_SET_RSS_KEY, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_ALLOC_VECTORS:
> +			iecm_set_msg_pending(adapter, &ctlq_msg,
> +					     IECM_VC_ALLOC_VECTORS_ERR);
> +			set_bit(IECM_VC_ALLOC_VECTORS, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_DEALLOC_VECTORS:
> +			if (ctlq_msg.cookie.mbx.chnl_retval)
> +				set_bit(IECM_VC_DEALLOC_VECTORS_ERR,
> +					adapter->vc_state);
> +			set_bit(IECM_VC_DEALLOC_VECTORS, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_GET_PTYPE_INFO:
> +			iecm_set_msg_pending(adapter, &ctlq_msg,
> +					     IECM_VC_GET_PTYPE_INFO_ERR);
> +			set_bit(IECM_VC_GET_PTYPE_INFO, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL2_OP_EVENT:
> +		case VIRTCHNL_OP_EVENT:
> +			if (iecm_set_msg_pending_bit(adapter)) {
> +				dev_info(&adapter->pdev->dev, "Timed out setting msg pending\n");
> +			} else {
> +				memcpy(adapter->vc_msg,
> +				       ctlq_msg.ctx.indirect.payload->va,
> +				       min_t(int, payload_size,
> +					     IECM_DFLT_MBX_BUF_SIZE));
> +				iecm_recv_event_msg(vport);
> +			}
> +			break;
> +		case VIRTCHNL_OP_ADD_ETH_ADDR:
> +			if (test_and_clear_bit(__IECM_ADD_ETH_REQ, adapter->flags)) {
> +				/* Message was sent asynchronously. We don't
> +				 * normally print errors here, instead
> +				 * preferring to handle errors in the function
> +				 * calling wait_for_event. However, we will
> +				 * have lost the context in which we sent the
> +				 * message if asynchronous. We can't really do
> +				 * anything about at it this point, but we
> +				 * should at a minimum indicate that it looks
> +				 * like something went wrong. Also don't bother
> +				 * setting ERR bit or waking vchnl_wq since no
> +				 * one will be waiting to read the async
> +				 * message.
> +				 */
> +				if (ctlq_msg.cookie.mbx.chnl_retval) {
> +					dev_err(&adapter->pdev->dev, "Failed to add MAC address: %d\n",
> +						ctlq_msg.cookie.mbx.chnl_retval);
> +				}
> +				break;
> +			}
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				set_bit(IECM_VC_ADD_ETH_ADDR_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_ADD_ETH_ADDR, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_DEL_ETH_ADDR:
> +			if (test_and_clear_bit(__IECM_DEL_ETH_REQ, adapter->flags)) {
> +				/* Message was sent asynchronously. We don't
> +				 * normally print errors here, instead
> +				 * preferring to handle errors in the function
> +				 * calling wait_for_event. However, we will
> +				 * have lost the context in which we sent the
> +				 * message if asynchronous. We can't really do
> +				 * anything about at it this point, but we
> +				 * should at a minimum indicate that it looks
> +				 * like something went wrong. Also don't bother
> +				 * setting ERR bit or waking vchnl_wq since no
> +				 * one will be waiting to read the async
> +				 * message.
> +				 */
> +				if (ctlq_msg.cookie.mbx.chnl_retval) {
> +					dev_err(&adapter->pdev->dev, "Failed to delete MAC address: %d\n",
> +						ctlq_msg.cookie.mbx.chnl_retval);
> +				}
> +				break;
> +			}
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				set_bit(IECM_VC_DEL_ETH_ADDR_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_DEL_ETH_ADDR, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				set_bit(IECM_VC_OFFLOAD_VLAN_V2_CAPS_ERR, adapter->vc_state);
> +			} else {
> +				memcpy(adapter->vc_msg,
> +				       ctlq_msg.ctx.indirect.payload->va,
> +				       min_t(int, payload_size,
> +					     IECM_DFLT_MBX_BUF_SIZE));
> +			}
> +			set_bit(IECM_VC_OFFLOAD_VLAN_V2_CAPS, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_ADD_VLAN_V2:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_err(&adapter->pdev->dev, "Failed to add vlan filter: %d\n",
> +					ctlq_msg.cookie.mbx.chnl_retval);
> +			}
> +			break;
> +		case VIRTCHNL_OP_DEL_VLAN_V2:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_err(&adapter->pdev->dev, "Failed to delete vlan filter: %d\n",
> +					ctlq_msg.cookie.mbx.chnl_retval);
> +			}
> +			break;
> +		case VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				set_bit(IECM_VC_INSERTION_ENA_VLAN_V2_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_INSERTION_ENA_VLAN_V2,
> +				adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				set_bit(IECM_VC_INSERTION_DIS_VLAN_V2_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_INSERTION_DIS_VLAN_V2,
> +				adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				set_bit(IECM_VC_STRIPPING_ENA_VLAN_V2_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_STRIPPING_ENA_VLAN_V2,
> +				adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				set_bit(IECM_VC_STRIPPING_DIS_VLAN_V2_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_STRIPPING_DIS_VLAN_V2,
> +				adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
> +			/* This message can only be sent asynchronously. As
> +			 * such we'll have lost the context in which it was
> +			 * called and thus can only really report if it looks
> +			 * like an error occurred. Don't bother setting ERR bit
> +			 * or waking chnl_wq since no will be waiting to
> +			 * reading message.
> +			 */
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_err(&adapter->pdev->dev, "Failed to set promiscuous mode: %d\n",
> +					ctlq_msg.cookie.mbx.chnl_retval);
> +			}
> +			break;
> +		case VIRTCHNL_OP_ADD_CLOUD_FILTER:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_err(&adapter->pdev->dev, "Failed to add cloud filter: %d\n",
> +					ctlq_msg.cookie.mbx.chnl_retval);
> +				set_bit(IECM_VC_ADD_CLOUD_FILTER_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_ADD_CLOUD_FILTER, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_DEL_CLOUD_FILTER:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_err(&adapter->pdev->dev, "Failed to delete cloud filter: %d\n",
> +					ctlq_msg.cookie.mbx.chnl_retval);
> +				set_bit(IECM_VC_DEL_CLOUD_FILTER_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_DEL_CLOUD_FILTER, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_ADD_RSS_CFG:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_err(&adapter->pdev->dev, "Failed to add RSS configuration: %d\n",
> +					ctlq_msg.cookie.mbx.chnl_retval);
> +				set_bit(IECM_VC_ADD_RSS_CFG_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_ADD_RSS_CFG, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_DEL_RSS_CFG:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_err(&adapter->pdev->dev, "Failed to delete RSS configuration: %d\n",
> +					ctlq_msg.cookie.mbx.chnl_retval);
> +				set_bit(IECM_VC_DEL_RSS_CFG_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_DEL_RSS_CFG, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_ADD_FDIR_FILTER:
> +			iecm_set_msg_pending(adapter, &ctlq_msg,
> +					     IECM_VC_ADD_FDIR_FILTER_ERR);
> +			set_bit(IECM_VC_ADD_FDIR_FILTER, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_DEL_FDIR_FILTER:
> +			iecm_set_msg_pending(adapter, &ctlq_msg,
> +					     IECM_VC_DEL_FDIR_FILTER_ERR);
> +			set_bit(IECM_VC_DEL_FDIR_FILTER, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_ENABLE_CHANNELS:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_err(&adapter->pdev->dev, "Failed to enable channels: %d\n",
> +					ctlq_msg.cookie.mbx.chnl_retval);
> +				set_bit(IECM_VC_ENA_CHANNELS_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_ENA_CHANNELS, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		case VIRTCHNL_OP_DISABLE_CHANNELS:
> +			if (ctlq_msg.cookie.mbx.chnl_retval) {
> +				dev_err(&adapter->pdev->dev, "Failed to disable channels: %d\n",
> +					ctlq_msg.cookie.mbx.chnl_retval);
> +				set_bit(IECM_VC_DIS_CHANNELS_ERR,
> +					adapter->vc_state);
> +			}
> +			set_bit(IECM_VC_DIS_CHANNELS, adapter->vc_state);
> +			wake_up(&adapter->vchnl_wq);
> +			break;
> +		default:
> +			if (adapter->dev_ops.vc_ops.recv_mbx_msg)
> +				err =
> +				adapter->dev_ops.vc_ops.recv_mbx_msg(adapter,
> +								   msg,
> +								   msg_size,
> +								   &ctlq_msg,
> +								   &work_done);
> +			else
> +				dev_warn(&adapter->pdev->dev,
> +					 "Unhandled virtchnl response %d\n",
> +					 ctlq_msg.cookie.mbx.chnl_opcode);
> +			break;
> +		} /* switch v_opcode */
> +post_buffs:
> +		if (ctlq_msg.data_len)
> +			dma_mem = ctlq_msg.ctx.indirect.payload;
> +		else
> +			num_q_msg = 0;
> +
> +		err = iecm_ctlq_post_rx_buffs(&adapter->hw, adapter->hw.arq,
> +					      &num_q_msg, &dma_mem);
> +		/* If post failed clear the only buffer we supplied */
> +		if (err && dma_mem)
> +			dmam_free_coherent(&adapter->pdev->dev, dma_mem->size,
> +					   dma_mem->va, dma_mem->pa);
> +		/* Applies only if we are looking for a specific opcode */
> +		if (work_done)
> +			break;
> +	}
> +
> +	return err;
> +}
> +EXPORT_SYMBOL(iecm_recv_mb_msg);
> +
> +/**
> + * iecm_send_ver_msg - send virtchnl version message
> + * @adapter: Driver specific private structure
> + *
> + * Send virtchnl version message.  Returns 0 on success, negative on failure.
> + */
> +static int iecm_send_ver_msg(struct iecm_adapter *adapter)
> +{
> +	struct virtchnl_version_info vvi;
> +
> +	if (adapter->virt_ver_maj) {
> +		vvi.major = adapter->virt_ver_maj;
> +		vvi.minor = adapter->virt_ver_min;
> +	} else {
> +		vvi.major = IECM_VIRTCHNL_VERSION_MAJOR;
> +		vvi.minor = IECM_VIRTCHNL_VERSION_MINOR;
> +	}
> +
> +	return iecm_send_mb_msg(adapter, VIRTCHNL_OP_VERSION, sizeof(vvi),
> +				(u8 *)&vvi);
> +}
> +
> +/**
> + * iecm_recv_ver_msg - Receive virtchnl version message
> + * @adapter: Driver specific private structure
> + *
> + * Receive virtchnl version message. Returns 0 on success, -EAGAIN if we need
> + * to send version message again, otherwise negative on failure.
> + */
> +static int iecm_recv_ver_msg(struct iecm_adapter *adapter)
> +{
> +	struct virtchnl_version_info vvi;
> +	int err = 0;
> +
> +	err = iecm_recv_mb_msg(adapter, VIRTCHNL_OP_VERSION, &vvi, sizeof(vvi));
> +	if (err)
> +		return err;
> +
> +	if (vvi.major > IECM_VIRTCHNL_VERSION_MAJOR) {
> +		dev_warn(&adapter->pdev->dev, "Virtchnl major version greater than supported\n");
> +		return -EINVAL;
> +	}
> +	if (vvi.major == IECM_VIRTCHNL_VERSION_MAJOR &&
> +	    vvi.minor > IECM_VIRTCHNL_VERSION_MINOR)
> +		dev_warn(&adapter->pdev->dev, "Virtchnl minor version not matched\n");
> +
> +	/* If we have a mismatch, resend version to update receiver on what
> +	 * version we will use.
> +	 */
> +	if (!adapter->virt_ver_maj &&
> +	    vvi.major != IECM_VIRTCHNL_VERSION_MAJOR &&
> +	    vvi.minor != IECM_VIRTCHNL_VERSION_MINOR)
> +		err = -EAGAIN;
> +
> +	adapter->virt_ver_maj = vvi.major;
> +	adapter->virt_ver_min = vvi.minor;
> +
> +	return err;
> +}
> +
> +/**
> + * iecm_send_get_caps_msg - Send virtchnl get capabilities message
> + * @adapter: Driver specific private structure
> + *
> + * Send virtchl get capabilities message. Returns 0 on success, negative on
> + * failure.
> + */
> +int iecm_send_get_caps_msg(struct iecm_adapter *adapter)
> +{
> +	struct virtchnl2_get_capabilities caps = {0};
> +	int buf_size;
> +
> +	buf_size = sizeof(struct virtchnl2_get_capabilities);
> +	adapter->caps = kzalloc(buf_size, GFP_KERNEL);
> +	if (!adapter->caps)
> +		return -ENOMEM;
> +
> +	caps.csum_caps =
> +		cpu_to_le32(VIRTCHNL2_CAP_TX_CSUM_L3_IPV4	|
> +			    VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_TCP	|
> +			    VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_UDP	|
> +			    VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_SCTP	|
> +			    VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_TCP	|
> +			    VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_UDP	|
> +			    VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_SCTP	|
> +			    VIRTCHNL2_CAP_TX_CSUM_GENERIC	|
> +			    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	|
> +			    VIRTCHNL2_CAP_RX_CSUM_GENERIC);
> +
> +	caps.seg_caps =
> +		cpu_to_le32(VIRTCHNL2_CAP_SEG_IPV4_TCP		|
> +			    VIRTCHNL2_CAP_SEG_IPV4_UDP		|
> +			    VIRTCHNL2_CAP_SEG_IPV4_SCTP		|
> +			    VIRTCHNL2_CAP_SEG_IPV6_TCP		|
> +			    VIRTCHNL2_CAP_SEG_IPV6_UDP		|
> +			    VIRTCHNL2_CAP_SEG_IPV6_SCTP		|
> +			    VIRTCHNL2_CAP_SEG_GENERIC);
> +
> +	caps.rss_caps =
> +		cpu_to_le64(VIRTCHNL2_CAP_RSS_IPV4_TCP		|
> +			    VIRTCHNL2_CAP_RSS_IPV4_UDP		|
> +			    VIRTCHNL2_CAP_RSS_IPV4_SCTP		|
> +			    VIRTCHNL2_CAP_RSS_IPV4_OTHER	|
> +			    VIRTCHNL2_CAP_RSS_IPV6_TCP		|
> +			    VIRTCHNL2_CAP_RSS_IPV6_UDP		|
> +			    VIRTCHNL2_CAP_RSS_IPV6_SCTP		|
> +			    VIRTCHNL2_CAP_RSS_IPV6_OTHER	|
> +			    VIRTCHNL2_CAP_RSS_IPV4_AH		|
> +			    VIRTCHNL2_CAP_RSS_IPV4_ESP		|
> +			    VIRTCHNL2_CAP_RSS_IPV4_AH_ESP	|
> +			    VIRTCHNL2_CAP_RSS_IPV6_AH		|
> +			    VIRTCHNL2_CAP_RSS_IPV6_ESP		|
> +			    VIRTCHNL2_CAP_RSS_IPV6_AH_ESP);
> +
> +	caps.hsplit_caps =
> +		cpu_to_le32(VIRTCHNL2_CAP_RX_HSPLIT_AT_L2	|
> +			    VIRTCHNL2_CAP_RX_HSPLIT_AT_L3	|
> +			    VIRTCHNL2_CAP_RX_HSPLIT_AT_L4V4	|
> +			    VIRTCHNL2_CAP_RX_HSPLIT_AT_L4V6);
> +
> +	caps.rsc_caps =
> +		cpu_to_le32(VIRTCHNL2_CAP_RSC_IPV4_TCP		|
> +			    VIRTCHNL2_CAP_RSC_IPV4_SCTP		|
> +			    VIRTCHNL2_CAP_RSC_IPV6_TCP		|
> +			    VIRTCHNL2_CAP_RSC_IPV6_SCTP);
> +
> +	caps.other_caps =
> +		cpu_to_le64(VIRTCHNL2_CAP_RDMA			|
> +			    VIRTCHNL2_CAP_SRIOV			|
> +			    VIRTCHNL2_CAP_MACFILTER		|
> +			    VIRTCHNL2_CAP_FLOW_DIRECTOR		|
> +			    VIRTCHNL2_CAP_SPLITQ_QSCHED		|
> +			    VIRTCHNL2_CAP_CRC			|
> +			    VIRTCHNL2_CAP_ADQ			|
> +			    VIRTCHNL2_CAP_WB_ON_ITR		|
> +			    VIRTCHNL2_CAP_PROMISC		|
> +			    VIRTCHNL2_CAP_INLINE_IPSEC		|
> +			    VIRTCHNL2_CAP_VLAN			|
> +			    VIRTCHNL2_CAP_RX_FLEX_DESC);
> +
> +	return iecm_send_mb_msg(adapter, VIRTCHNL2_OP_GET_CAPS, sizeof(caps),
> +				(u8 *)&caps);
> +}
> +EXPORT_SYMBOL(iecm_send_get_caps_msg);
> +
> +/**
> + * iecm_recv_get_caps_msg - Receive virtchnl get capabilities message
> + * @adapter: Driver specific private structure
> + *
> + * Receive virtchnl get capabilities message.  Returns 0 on succes, negative on
> + * failure.
> + */
> +static int iecm_recv_get_caps_msg(struct iecm_adapter *adapter)
> +{
> +	return iecm_recv_mb_msg(adapter, VIRTCHNL2_OP_GET_CAPS, adapter->caps,
> +				sizeof(struct virtchnl2_get_capabilities));
> +}
> +
> +/**
> + * iecm_send_create_vport_msg - Send virtchnl create vport message
> + * @adapter: Driver specific private structure
> + *
> + * send virtchnl creae vport message
> + *
> + * Returns 0 on success, negative on failure
> + */
> +static int iecm_send_create_vport_msg(struct iecm_adapter *adapter)
> +{
> +	/* stub */
> +	return 0;
> +}
> +
> +/**
> + * iecm_recv_create_vport_msg - Receive virtchnl create vport message
> + * @adapter: Driver specific private structure
> + * @vport_id: Virtual port identifier
> + *
> + * Receive virtchnl create vport message.  Returns 0 on success, negative on
> + * failure.
> + */
> +static int iecm_recv_create_vport_msg(struct iecm_adapter *adapter,
> +				      int *vport_id)
> +{
> +	/* stub */
> +	return 0;
> +}
> +
> +/**
> + * __iecm_wait_for_event - wrapper function for wait on virtchannel response
> + * @adapter: Driver private data structure
> + * @state: check on state upon timeout
> + * @err_check: check if this specific error bit is set
> + * @timeout: Max time to wait
> + *
> + * Checks if state is set upon expiry of timeout.  Returns 0 on success,
> + * negative on failure.
> + */
> +static int __iecm_wait_for_event(struct iecm_adapter *adapter,
> +				 enum iecm_vport_vc_state state,
> +				 enum iecm_vport_vc_state err_check,
> +				 int timeout)
> +{
> +	int event;
> +
> +	event = wait_event_timeout(adapter->vchnl_wq,
> +				   test_and_clear_bit(state, adapter->vc_state),
> +				   msecs_to_jiffies(timeout));
> +	if (event) {
> +		if (test_and_clear_bit(err_check, adapter->vc_state)) {
> +			dev_err(&adapter->pdev->dev, "VC response error %s\n",
> +				iecm_vport_vc_state_str[err_check]);
> +			return -EINVAL;
> +		}
> +		return 0;
> +	}
> +
> +	/* Timeout occurred */
> +	dev_err(&adapter->pdev->dev, "VC timeout, state = %s\n",
> +		iecm_vport_vc_state_str[state]);
> +	return -ETIMEDOUT;
> +}
> +
> +/**
> + * iecm_min_wait_for_event - wait for virtchannel response
> + * @adapter: Driver private data structure
> + * @state: check on state upon timeout
> + * @err_check: check if this specific error bit is set
> + *
> + * Returns 0 on success, negative on failure.
> + */
> +int iecm_min_wait_for_event(struct iecm_adapter *adapter,
> +			    enum iecm_vport_vc_state state,
> +			    enum iecm_vport_vc_state err_check)
> +{
> +	int timeout = 2000;
> +
> +	return __iecm_wait_for_event(adapter, state, err_check, timeout);
> +}
> +EXPORT_SYMBOL(iecm_min_wait_for_event);
> +
> +/**
> + * iecm_wait_for_event - wait for virtchannel response
> + * @adapter: Driver private data structure
> + * @state: check on state upon timeout after 500ms
> + * @err_check: check if this specific error bit is set
> + *
> + * Returns 0 on success, negative on failure.
> + */
> +int iecm_wait_for_event(struct iecm_adapter *adapter,
> +			enum iecm_vport_vc_state state,
> +			enum iecm_vport_vc_state err_check)
> +{
> +	/* Increasing the timeout in __IECM_INIT_SW flow to consider large
> +	 * number of VF's mailbox message responses. When a message is received
> +	 * on mailbox, this thread is wake up by the iecm_recv_mb_msg before the
> +	 * timeout expires. Only in the error case i.e. if no message is
> +	 * received on mailbox, we wait for the complete timeout which is
> +	 * less likely to happen.
> +	 */
> +	int timeout = 60000;

If you make a definition from it, it would be easier to find it
later in case of adjustments needed.

> +
> +	return __iecm_wait_for_event(adapter, state, err_check, timeout);
> +}
> +EXPORT_SYMBOL(iecm_wait_for_event);
> +
>  /**
>   * iecm_find_ctlq - Given a type and id, find ctlq info
>   * @hw: hardware struct
> @@ -170,3 +1097,375 @@ void iecm_vport_params_buf_rel(struct iecm_adapter *adapter)
>  	kfree(adapter->caps);
>  	kfree(adapter->config_data.req_qs_chunks);
>  }
> +
> +/**
> + * iecm_vc_core_init - Initialize mailbox and get resources
> + * @adapter: Driver specific private structure
> + * @vport_id: Virtual port identifier
> + *
> + * Will check if HW is ready with reset complete. Initializes the mailbox and
> + * communicate with master to get all the default vport parameters. Returns 0
> + * on success, -EAGAIN function will get called again, otherwise negative on
> + * failure.
> + */
> +int iecm_vc_core_init(struct iecm_adapter *adapter, int *vport_id)
> +{
> +	int err;
> +
> +	switch (adapter->state) {
> +	case __IECM_STARTUP:
> +		if (iecm_send_ver_msg(adapter))
> +			goto init_failed;
> +		adapter->state = __IECM_VER_CHECK;
> +		goto restart;
> +	case __IECM_VER_CHECK:
> +		err = iecm_recv_ver_msg(adapter);
> +		if (err == -EAGAIN) {
> +			adapter->state = __IECM_STARTUP;
> +			goto restart;
> +		} else if (err) {
> +			goto init_failed;
> +		}
> +		adapter->state = __IECM_GET_CAPS;
> +		if (adapter->dev_ops.vc_ops.get_caps(adapter))
> +			goto init_failed;
> +		goto restart;
> +	case __IECM_GET_CAPS:
> +		if (iecm_recv_get_caps_msg(adapter))
> +			goto init_failed;
> +		if (iecm_send_create_vport_msg(adapter))
> +			goto init_failed;
> +		adapter->state = __IECM_GET_DFLT_VPORT_PARAMS;
> +		goto restart;
> +	case __IECM_GET_DFLT_VPORT_PARAMS:
> +		if (iecm_recv_create_vport_msg(adapter, vport_id))
> +			goto init_failed;
> +		adapter->state = __IECM_INIT_SW;
> +		break;
> +	case __IECM_INIT_SW:
> +		break;
> +	default:
> +		dev_err(&adapter->pdev->dev, "Device is in bad state: %d\n",
> +			adapter->state);
> +		goto init_failed;
> +	}
> +
> +	return 0;
> +restart:
> +	queue_delayed_work(adapter->init_wq, &adapter->init_task,
> +			   msecs_to_jiffies(30));
> +	/* Not an error. Using try again to continue with state machine */
> +	return -EAGAIN;
> +init_failed:
> +	if (++adapter->mb_wait_count > IECM_MB_MAX_ERR) {
> +		dev_err(&adapter->pdev->dev, "Failed to establish mailbox communications with hardware\n");
> +		return -EFAULT;
> +	}
> +	adapter->state = __IECM_STARTUP;
> +	/* If it reaches here, it is possible that mailbox queue initialization
> +	 * register writes might not have taken effect. Retry to initialize
> +	 * the mailbox again
> +	 */
> +	iecm_deinit_dflt_mbx(adapter);
> +	set_bit(__IECM_HR_DRV_LOAD, adapter->flags);
> +	queue_delayed_work(adapter->vc_event_wq, &adapter->vc_event_task,
> +			   msecs_to_jiffies(20));
> +	return -EAGAIN;
> +}
> +EXPORT_SYMBOL(iecm_vc_core_init);
> +
> +/**
> + * iecm_vport_init - Initialize virtual port
> + * @vport: virtual port to be initialized
> + * @vport_id: Unique identification number of vport
> + *
> + * Will initialize vport with the info received through MB earlier
> + */
> +static void iecm_vport_init(struct iecm_vport *vport,
> +			    __always_unused int vport_id)
> +{
> +	struct virtchnl2_create_vport *vport_msg;
> +	u16 rx_itr[] = {2, 8, 32, 96, 128};
> +	u16 tx_itr[] = {2, 8, 64, 128, 256};
> +
> +	vport_msg = (struct virtchnl2_create_vport *)
> +				vport->adapter->vport_params_recvd[0];
> +	vport->txq_model = le16_to_cpu(vport_msg->txq_model);
> +	vport->rxq_model = le16_to_cpu(vport_msg->rxq_model);
> +	vport->vport_type = le16_to_cpu(vport_msg->vport_type);
> +	vport->vport_id = le32_to_cpu(vport_msg->vport_id);
> +	vport->adapter->rss_data.rss_key_size =
> +				min_t(u16, NETDEV_RSS_KEY_LEN,
> +				      le16_to_cpu(vport_msg->rss_key_size));
> +	vport->adapter->rss_data.rss_lut_size =
> +				le16_to_cpu(vport_msg->rss_lut_size);
> +	ether_addr_copy(vport->default_mac_addr, vport_msg->default_mac_addr);
> +	vport->max_mtu = IECM_MAX_MTU;
> +
> +	if (iecm_is_queue_model_split(vport->rxq_model)) {
> +		vport->num_bufqs_per_qgrp = IECM_MAX_BUFQS_PER_RXQ_GRP;
> +		/* Bufq[0] default buffer size is 4K
> +		 * Bufq[1] default buffer size is 2K
> +		 */
> +		vport->bufq_size[0] = IECM_RX_BUF_4096;
> +		vport->bufq_size[1] = IECM_RX_BUF_2048;
> +	} else {
> +		vport->num_bufqs_per_qgrp = 0;
> +		vport->bufq_size[0] = IECM_RX_BUF_2048;
> +	}
> +
> +	/*Initialize Tx and Rx profiles for Dynamic Interrupt Moderation */
> +	memcpy(vport->rx_itr_profile, rx_itr, IECM_DIM_PROFILE_SLOTS);
> +	memcpy(vport->tx_itr_profile, tx_itr, IECM_DIM_PROFILE_SLOTS);
> +}
> +
> +/**
> + * iecm_get_vec_ids - Initialize vector id from Mailbox parameters
> + * @adapter: adapter structure to get the mailbox vector id
> + * @vecids: Array of vector ids
> + * @num_vecids: number of vector ids
> + * @chunks: vector ids received over mailbox
> + *
> + * Will initialize the mailbox vector id which is received from the
> + * get capabilities and data queue vector ids with ids received as
> + * mailbox parameters.
> + * Returns number of ids filled
> + */
> +int iecm_get_vec_ids(struct iecm_adapter *adapter,
> +		     u16 *vecids, int num_vecids,
> +		     struct virtchnl2_vector_chunks *chunks)
> +{
> +	u16 num_chunks = le16_to_cpu(chunks->num_vchunks);
> +	u16 start_vecid, num_vec;
> +	int num_vecid_filled = 0;
> +	int i, j;
> +
> +	vecids[num_vecid_filled] = adapter->mb_vector.v_idx;
> +	num_vecid_filled++;
> +
> +	for (j = 0; j < num_chunks; j++) {
> +		struct virtchnl2_vector_chunk *chunk = &chunks->vchunks[j];
> +
> +		num_vec = le16_to_cpu(chunk->num_vectors);
> +		start_vecid = le16_to_cpu(chunk->start_vector_id);
> +		for (i = 0; i < num_vec; i++) {
> +			if ((num_vecid_filled + i) < num_vecids) {
> +				vecids[num_vecid_filled + i] = start_vecid;
> +				start_vecid++;
> +			} else {
> +				break;
> +			}
> +		}
> +		num_vecid_filled = num_vecid_filled + i;
> +	}
> +
> +	return num_vecid_filled;
> +}
> +
> +/**
> + * iecm_vport_get_queue_ids - Initialize queue id from Mailbox parameters
> + * @qids: Array of queue ids
> + * @num_qids: number of queue ids
> + * @q_type: queue model
> + * @chunks: queue ids received over mailbox
> + *
> + * Will initialize all queue ids with ids received as mailbox parameters
> + * Returns number of ids filled
> + */
> +static int
> +iecm_vport_get_queue_ids(u32 *qids, int num_qids, u16 q_type,
> +			 struct virtchnl2_queue_reg_chunks *chunks)
> +{
> +	u16 num_chunks = le16_to_cpu(chunks->num_chunks);
> +	u32 num_q_id_filled = 0, i;
> +	u32 start_q_id, num_q;
> +
> +	while (num_chunks) {
> +		struct virtchnl2_queue_reg_chunk *chunk = &chunks->chunks[num_chunks - 1];
> +
> +		if (le32_to_cpu(chunk->type) == q_type) {
> +			num_q = le32_to_cpu(chunk->num_queues);
> +			start_q_id = le32_to_cpu(chunk->start_queue_id);
> +			for (i = 0; i < num_q; i++) {
> +				if ((num_q_id_filled + i) < num_qids) {
> +					qids[num_q_id_filled + i] = start_q_id;
> +					start_q_id++;
> +				} else {
> +					break;
> +				}
> +			}
> +			num_q_id_filled = num_q_id_filled + i;
> +		}
> +		num_chunks--;
> +	}
> +
> +	return num_q_id_filled;
> +}
> +
> +/**
> + * __iecm_vport_queue_ids_init - Initialize queue ids from Mailbox parameters
> + * @vport: virtual port for which the queues ids are initialized
> + * @qids: queue ids
> + * @num_qids: number of queue ids
> + * @q_type: type of queue
> + *
> + * Will initialize all queue ids with ids received as mailbox
> + * parameters. Returns number of queue ids initialized.
> + */
> +static int
> +__iecm_vport_queue_ids_init(struct iecm_vport *vport, u32 *qids,
> +			    int num_qids, u32 q_type)
> +{
> +	/* stub */
> +	return 0;
> +}
> +
> +/**
> + * iecm_vport_queue_ids_init - Initialize queue ids from Mailbox parameters
> + * @vport: virtual port for which the queues ids are initialized
> + *
> + * Will initialize all queue ids with ids received as mailbox parameters.
> + * Returns 0 on success, negative if all the queues are not initialized.
> + */
> +static int iecm_vport_queue_ids_init(struct iecm_vport *vport)
> +{
> +	struct virtchnl2_create_vport *vport_params;
> +	struct virtchnl2_queue_reg_chunks *chunks;
> +	/* We may never deal with more than 256 same type of queues */
> +#define IECM_MAX_QIDS	256
> +	u32 qids[IECM_MAX_QIDS];
> +	int num_ids;
> +	u16 q_type;
> +
> +	if (vport->adapter->config_data.req_qs_chunks) {
> +		struct virtchnl2_add_queues *vc_aq =
> +			(struct virtchnl2_add_queues *)
> +			vport->adapter->config_data.req_qs_chunks;
> +		chunks = &vc_aq->chunks;
> +	} else {
> +		vport_params = (struct virtchnl2_create_vport *)
> +				vport->adapter->vport_params_recvd[0];
> +		chunks = &vport_params->chunks;
> +	}
> +
> +	num_ids = iecm_vport_get_queue_ids(qids, IECM_MAX_QIDS,
> +					   VIRTCHNL2_QUEUE_TYPE_TX,
> +					   chunks);
> +	if (num_ids != vport->num_txq)
> +		return -EINVAL;
> +	num_ids = __iecm_vport_queue_ids_init(vport, qids, num_ids,
> +					      VIRTCHNL2_QUEUE_TYPE_TX);
> +	if (num_ids != vport->num_txq)
> +		return -EINVAL;
> +	num_ids = iecm_vport_get_queue_ids(qids, IECM_MAX_QIDS,
> +					   VIRTCHNL2_QUEUE_TYPE_RX,
> +					   chunks);
> +	if (num_ids != vport->num_rxq)
> +		return -EINVAL;
> +	num_ids = __iecm_vport_queue_ids_init(vport, qids, num_ids,
> +					      VIRTCHNL2_QUEUE_TYPE_RX);
> +	if (num_ids != vport->num_rxq)
> +		return -EINVAL;
> +
> +	if (iecm_is_queue_model_split(vport->txq_model)) {
> +		q_type = VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION;
> +		num_ids = iecm_vport_get_queue_ids(qids, IECM_MAX_QIDS, q_type,
> +						   chunks);
> +		if (num_ids != vport->num_complq)
> +			return -EINVAL;
> +		num_ids = __iecm_vport_queue_ids_init(vport, qids,
> +						      num_ids,
> +						      q_type);
> +		if (num_ids != vport->num_complq)
> +			return -EINVAL;
> +	}
> +
> +	if (iecm_is_queue_model_split(vport->rxq_model)) {
> +		q_type = VIRTCHNL2_QUEUE_TYPE_RX_BUFFER;
> +		num_ids = iecm_vport_get_queue_ids(qids, IECM_MAX_QIDS, q_type,
> +						   chunks);
> +		if (num_ids != vport->num_bufq)
> +			return -EINVAL;
> +		num_ids = __iecm_vport_queue_ids_init(vport, qids, num_ids,
> +						      q_type);
> +		if (num_ids != vport->num_bufq)
> +			return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * iecm_is_capability_ena - Default implementation of capability checking
> + * @adapter: Private data struct
> + * @all: all or one flag
> + * @field: caps field to check for flags
> + * @flag: flag to check
> + *
> + * Return true if all capabilities are supported, false otherwise
> + */
> +static bool iecm_is_capability_ena(struct iecm_adapter *adapter, bool all,
> +				   enum iecm_cap_field field, u64 flag)
> +{
> +	u8 *caps = (u8 *)adapter->caps;
> +	u32 *cap_field;
> +
> +	if (field == IECM_BASE_CAPS)
> +		return false;
> +	if (field >= IECM_CAP_FIELD_LAST) {
> +		dev_err(&adapter->pdev->dev, "Bad capability field: %d\n",
> +			field);
> +		return false;
> +	}
> +	cap_field = (u32 *)(caps + field);
> +
> +	if (all)
> +		return (*cap_field & flag) == flag;
> +	else
> +		return !!(*cap_field & flag);
> +}
> +
> +/**
> + * iecm_vc_ops_init - Initialize virtchnl common api
> + * @adapter: Driver specific private structure
> + *
> + * Initialize the function pointers with the extended feature set functions
> + * as APF will deal only with new set of opcodes.
> + */
> +void iecm_vc_ops_init(struct iecm_adapter *adapter)
> +{
> +	struct iecm_virtchnl_ops *vc_ops = &adapter->dev_ops.vc_ops;
> +
> +	vc_ops->core_init = iecm_vc_core_init;
> +	vc_ops->vport_init = iecm_vport_init;
> +	vc_ops->vport_queue_ids_init = iecm_vport_queue_ids_init;
> +	vc_ops->get_caps = iecm_send_get_caps_msg;
> +	vc_ops->is_cap_ena = iecm_is_capability_ena;
> +	vc_ops->get_reserved_vecs = NULL;
> +	vc_ops->config_queues = NULL;
> +	vc_ops->enable_queues = NULL;
> +	vc_ops->disable_queues = NULL;
> +	vc_ops->add_queues = NULL;
> +	vc_ops->delete_queues = NULL;
> +	vc_ops->irq_map_unmap = NULL;
> +	vc_ops->enable_vport = NULL;
> +	vc_ops->disable_vport = NULL;
> +	vc_ops->destroy_vport = NULL;
> +	vc_ops->get_ptype = NULL;
> +	vc_ops->get_set_rss_key = NULL;
> +	vc_ops->get_set_rss_lut = NULL;
> +	vc_ops->get_set_rss_hash = NULL;
> +	vc_ops->adjust_qs = NULL;
> +	vc_ops->add_del_vlans = NULL;
> +	vc_ops->strip_vlan_msg = NULL;
> +	vc_ops->insert_vlan_msg = NULL;
> +	vc_ops->init_max_queues = NULL;
> +	vc_ops->get_max_tx_bufs = NULL;
> +	vc_ops->vportq_reg_init = NULL;
> +	vc_ops->alloc_vectors = NULL;
> +	vc_ops->dealloc_vectors = NULL;
> +	vc_ops->get_supported_desc_ids = NULL;
> +	vc_ops->get_stats_msg = NULL;
> +	vc_ops->recv_mbx_msg = NULL;
> +}
> +EXPORT_SYMBOL(iecm_vc_ops_init);
> diff --git a/drivers/net/ethernet/intel/include/iecm.h b/drivers/net/ethernet/intel/include/iecm.h
> index ca9029224e06..994664dfe419 100644
> --- a/drivers/net/ethernet/intel/include/iecm.h
> +++ b/drivers/net/ethernet/intel/include/iecm.h
> @@ -7,10 +7,13 @@
>  #include <linux/aer.h>
>  #include <linux/pci.h>
>  #include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
>  #include <linux/ethtool.h>
> +#include <net/tcp.h>
>  #include <linux/version.h>
>  #include <linux/dim.h>
>  
> +#include "virtchnl_2.h"
>  #include "iecm_txrx.h"
>  #include "iecm_controlq.h"
>  
> @@ -35,10 +38,34 @@
>  /* available message levels */
>  #define IECM_AVAIL_NETIF_M (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
>  
> +#define IECM_VIRTCHNL_VERSION_MAJOR VIRTCHNL_VERSION_MAJOR_2
> +#define IECM_VIRTCHNL_VERSION_MINOR VIRTCHNL_VERSION_MINOR_0
> +
>  /* Forward declaration */
>  struct iecm_adapter;
>  struct iecm_vport;
>  
> +struct iecm_mac_filter {
> +	struct list_head list;
> +	u8 macaddr[ETH_ALEN];
> +	bool remove;		/* filter needs to be removed */
> +	bool add;		/* filter needs to be added */
> +};
> +
> +#define IECM_VLAN(vid, tpid) ((struct iecm_vlan){ vid, tpid })
> +
> +struct iecm_vlan {
> +	u16 vid;
> +	u16 tpid;
> +};
> +
> +struct iecm_vlan_filter {
> +	struct list_head list;
> +	struct iecm_vlan vlan;
> +	bool remove;		/* filter needs to be removed */
> +	bool add;		/* filter needs to be added */
> +};
> +
>  enum iecm_state {
>  	__IECM_STARTUP,
>  	__IECM_VER_CHECK,
> @@ -90,6 +117,24 @@ enum iecm_flags {
>  	__IECM_FLAGS_NBITS,
>  };
>  
> +/* enum used to distinquish which capability field to check */
> +enum iecm_cap_field {
> +	IECM_BASE_CAPS		= -1,
> +	IECM_CSUM_CAPS		= offsetof(struct virtchnl2_get_capabilities,
> +					   csum_caps),
> +	IECM_SEG_CAPS		= offsetof(struct virtchnl2_get_capabilities,
> +					   seg_caps),
> +	IECM_RSS_CAPS		= offsetof(struct virtchnl2_get_capabilities,
> +					   rss_caps),
> +	IECM_HSPLIT_CAPS	= offsetof(struct virtchnl2_get_capabilities,
> +					   hsplit_caps),
> +	IECM_RSC_CAPS		= offsetof(struct virtchnl2_get_capabilities,
> +					   rsc_caps),
> +	IECM_OTHER_CAPS		= offsetof(struct virtchnl2_get_capabilities,
> +					   other_caps),
> +	IECM_CAP_FIELD_LAST,
> +};
> +
>  struct iecm_reset_reg {
>  	u32 rstat;
>  	u32 rstat_m;
> @@ -105,14 +150,229 @@ struct iecm_reg_ops {
>  			      enum iecm_flags trig_cause);
>  };
>  
> +struct iecm_virtchnl_ops {
> +	int (*core_init)(struct iecm_adapter *adapter, int *vport_id);
> +	void (*vport_init)(struct iecm_vport *vport, int vport_id);
> +	int (*vport_queue_ids_init)(struct iecm_vport *vport);
> +	int (*get_caps)(struct iecm_adapter *adapter);
> +	int (*config_queues)(struct iecm_vport *vport);
> +	int (*enable_queues)(struct iecm_vport *vport);
> +	int (*disable_queues)(struct iecm_vport *vport);
> +	int (*add_queues)(struct iecm_vport *vport, u16 num_tx_q,
> +			  u16 num_complq, u16 num_rx_q,
> +			  u16 num_rx_bufq);
> +	int (*delete_queues)(struct iecm_vport *vport);
> +	int (*irq_map_unmap)(struct iecm_vport *vport, bool map);
> +	int (*enable_vport)(struct iecm_vport *vport);
> +	int (*disable_vport)(struct iecm_vport *vport);
> +	int (*destroy_vport)(struct iecm_vport *vport);
> +	int (*get_ptype)(struct iecm_vport *vport);
> +	int (*get_set_rss_key)(struct iecm_vport *vport, bool get);
> +	int (*get_set_rss_lut)(struct iecm_vport *vport, bool get);
> +	int (*get_set_rss_hash)(struct iecm_vport *vport, bool get);
> +	void (*adjust_qs)(struct iecm_vport *vport);
> +	int (*recv_mbx_msg)(struct iecm_adapter *adapter,
> +			    void *msg, int msg_size,
> +			    struct iecm_ctlq_msg *ctlq_msg, bool *work_done);
> +	bool (*is_cap_ena)(struct iecm_adapter *adapter, bool all,
> +			   enum iecm_cap_field field, u64 flag);
> +	u16 (*get_reserved_vecs)(struct iecm_adapter *adapter);
> +	void (*add_del_vlans)(struct iecm_vport *vport, bool add);
> +	int (*strip_vlan_msg)(struct iecm_vport *vport, bool ena);
> +	int (*insert_vlan_msg)(struct iecm_vport *vport, bool ena);
> +	void (*init_max_queues)(struct iecm_adapter *adapter);
> +	unsigned int (*get_max_tx_bufs)(struct iecm_adapter *adapter);
> +	int (*vportq_reg_init)(struct iecm_vport *vport);
> +	int (*alloc_vectors)(struct iecm_adapter *adapter, u16 num_vectors);
> +	int (*dealloc_vectors)(struct iecm_adapter *adapter);
> +	int (*get_supported_desc_ids)(struct iecm_vport *vport);
> +	int (*get_stats_msg)(struct iecm_vport *vport);
> +};
> +
>  struct iecm_dev_ops {
>  	void (*reg_ops_init)(struct iecm_adapter *adapter);
> +	void (*vc_ops_init)(struct iecm_adapter *adapter);
>  	void (*crc_enable)(u64 *td_cmd);
>  	struct iecm_reg_ops reg_ops;
> +	struct iecm_virtchnl_ops vc_ops;
> +};
> +
> +/* These macros allow us to generate an enum and a matching char * array of
> + * stringified enums that are always in sync. Checkpatch issues a bogus warning
> + * about this being a complex macro; but it's wrong, these are never used as a
> + * statement and instead only used to define the enum and array.
> + */
> +#define IECM_FOREACH_VPORT_VC_STATE(STATE)	\
> +	STATE(IECM_VC_ENA_VPORT)		\
> +	STATE(IECM_VC_ENA_VPORT_ERR)		\
> +	STATE(IECM_VC_DIS_VPORT)		\
> +	STATE(IECM_VC_DIS_VPORT_ERR)		\
> +	STATE(IECM_VC_DESTROY_VPORT)		\
> +	STATE(IECM_VC_DESTROY_VPORT_ERR)	\
> +	STATE(IECM_VC_CONFIG_TXQ)		\
> +	STATE(IECM_VC_CONFIG_TXQ_ERR)		\
> +	STATE(IECM_VC_CONFIG_RXQ)		\
> +	STATE(IECM_VC_CONFIG_RXQ_ERR)		\
> +	STATE(IECM_VC_CONFIG_Q)			\
> +	STATE(IECM_VC_CONFIG_Q_ERR)		\
> +	STATE(IECM_VC_ENA_QUEUES)		\
> +	STATE(IECM_VC_ENA_QUEUES_ERR)		\
> +	STATE(IECM_VC_DIS_QUEUES)		\
> +	STATE(IECM_VC_DIS_QUEUES_ERR)		\
> +	STATE(IECM_VC_ENA_CHANNELS)		\
> +	STATE(IECM_VC_ENA_CHANNELS_ERR)		\
> +	STATE(IECM_VC_DIS_CHANNELS)		\
> +	STATE(IECM_VC_DIS_CHANNELS_ERR)		\
> +	STATE(IECM_VC_MAP_IRQ)			\
> +	STATE(IECM_VC_MAP_IRQ_ERR)		\
> +	STATE(IECM_VC_UNMAP_IRQ)		\
> +	STATE(IECM_VC_UNMAP_IRQ_ERR)		\
> +	STATE(IECM_VC_ADD_QUEUES)		\
> +	STATE(IECM_VC_ADD_QUEUES_ERR)		\
> +	STATE(IECM_VC_DEL_QUEUES)		\
> +	STATE(IECM_VC_REQUEST_QUEUES)		\
> +	STATE(IECM_VC_REQUEST_QUEUES_ERR)	\
> +	STATE(IECM_VC_DEL_QUEUES_ERR)		\
> +	STATE(IECM_VC_ALLOC_VECTORS)		\
> +	STATE(IECM_VC_ALLOC_VECTORS_ERR)	\
> +	STATE(IECM_VC_DEALLOC_VECTORS)		\
> +	STATE(IECM_VC_DEALLOC_VECTORS_ERR)	\
> +	STATE(IECM_VC_SET_SRIOV_VFS)		\
> +	STATE(IECM_VC_SET_SRIOV_VFS_ERR)	\
> +	STATE(IECM_VC_GET_RSS_HASH)		\
> +	STATE(IECM_VC_GET_RSS_HASH_ERR)		\
> +	STATE(IECM_VC_SET_RSS_HASH)		\
> +	STATE(IECM_VC_SET_RSS_HASH_ERR)		\
> +	STATE(IECM_VC_GET_RSS_LUT)		\
> +	STATE(IECM_VC_GET_RSS_LUT_ERR)		\
> +	STATE(IECM_VC_SET_RSS_LUT)		\
> +	STATE(IECM_VC_SET_RSS_LUT_ERR)		\
> +	STATE(IECM_VC_GET_RSS_KEY)		\
> +	STATE(IECM_VC_GET_RSS_KEY_ERR)		\
> +	STATE(IECM_VC_SET_RSS_KEY)		\
> +	STATE(IECM_VC_SET_RSS_KEY_ERR)		\
> +	STATE(IECM_VC_GET_STATS)		\
> +	STATE(IECM_VC_GET_STATS_ERR)		\
> +	STATE(IECM_VC_ENA_STRIP_VLAN_TAG)	\
> +	STATE(IECM_VC_ENA_STRIP_VLAN_TAG_ERR)	\
> +	STATE(IECM_VC_DIS_STRIP_VLAN_TAG)	\
> +	STATE(IECM_VC_DIS_STRIP_VLAN_TAG_ERR)	\
> +	STATE(IECM_VC_IWARP_IRQ_MAP)		\
> +	STATE(IECM_VC_IWARP_IRQ_MAP_ERR)	\
> +	STATE(IECM_VC_ADD_ETH_ADDR)		\
> +	STATE(IECM_VC_ADD_ETH_ADDR_ERR)		\
> +	STATE(IECM_VC_DEL_ETH_ADDR)		\
> +	STATE(IECM_VC_DEL_ETH_ADDR_ERR)		\
> +	STATE(IECM_VC_PROMISC)			\
> +	STATE(IECM_VC_ADD_CLOUD_FILTER)		\
> +	STATE(IECM_VC_ADD_CLOUD_FILTER_ERR)	\
> +	STATE(IECM_VC_DEL_CLOUD_FILTER)		\
> +	STATE(IECM_VC_DEL_CLOUD_FILTER_ERR)	\
> +	STATE(IECM_VC_ADD_RSS_CFG)		\
> +	STATE(IECM_VC_ADD_RSS_CFG_ERR)		\
> +	STATE(IECM_VC_DEL_RSS_CFG)		\
> +	STATE(IECM_VC_DEL_RSS_CFG_ERR)		\
> +	STATE(IECM_VC_ADD_FDIR_FILTER)		\
> +	STATE(IECM_VC_ADD_FDIR_FILTER_ERR)	\
> +	STATE(IECM_VC_DEL_FDIR_FILTER)		\
> +	STATE(IECM_VC_DEL_FDIR_FILTER_ERR)	\
> +	STATE(IECM_VC_OFFLOAD_VLAN_V2_CAPS)	\
> +	STATE(IECM_VC_OFFLOAD_VLAN_V2_CAPS_ERR)	\
> +	STATE(IECM_VC_INSERTION_ENA_VLAN_V2)	\
> +	STATE(IECM_VC_INSERTION_ENA_VLAN_V2_ERR)\
> +	STATE(IECM_VC_INSERTION_DIS_VLAN_V2)	\
> +	STATE(IECM_VC_INSERTION_DIS_VLAN_V2_ERR)\
> +	STATE(IECM_VC_STRIPPING_ENA_VLAN_V2)	\
> +	STATE(IECM_VC_STRIPPING_ENA_VLAN_V2_ERR)\
> +	STATE(IECM_VC_STRIPPING_DIS_VLAN_V2)	\
> +	STATE(IECM_VC_STRIPPING_DIS_VLAN_V2_ERR)\
> +	STATE(IECM_VC_GET_SUPPORTED_RXDIDS)	\
> +	STATE(IECM_VC_GET_SUPPORTED_RXDIDS_ERR)	\
> +	STATE(IECM_VC_GET_PTYPE_INFO)		\
> +	STATE(IECM_VC_GET_PTYPE_INFO_ERR)	\
> +	STATE(IECM_VC_NBITS)
> +
> +#define IECM_GEN_ENUM(ENUM) ENUM,
> +#define IECM_GEN_STRING(STRING) #STRING,
> +
> +enum iecm_vport_vc_state {
> +	IECM_FOREACH_VPORT_VC_STATE(IECM_GEN_ENUM)
> +};
> +
> +extern const char * const iecm_vport_vc_state_str[];
> +
> +enum iecm_vport_flags {
> +	__IECM_VPORT_INIT_PROMISC,
> +	__IECM_VPORT_FLAGS_NBITS,
> +};
> +
> +struct iecm_port_stats {
> +	struct u64_stats_sync stats_sync;
> +	u64 rx_hw_csum_err;
> +	u64 rx_hsplit;
> +	u64 rx_hsplit_hbo;
> +	u64 tx_linearize;
> +	u64 rx_bad_descs;
> +	struct virtchnl2_vport_stats vport_stats;
> +	struct virtchnl_eth_stats eth_stats;
>  };
>  
> -/* stub */
>  struct iecm_vport {
> +	/* TX */
> +	int num_txq;
> +	int num_complq;
> +	/* It makes more sense for descriptor count to be part of only idpf
> +	 * queue structure. But when user changes the count via ethtool, driver
> +	 * has to store that value somewhere other than queue structure as the
> +	 * queues will be freed and allocated again.
> +	 */
> +	int txq_desc_count;
> +	int complq_desc_count;
> +	int compln_clean_budget;
> +	int num_txq_grp;
> +	struct iecm_txq_group *txq_grps;
> +	u32 txq_model;
> +	/* Used only in hotpath to get to the right queue very fast */
> +	struct iecm_queue **txqs;
> +	DECLARE_BITMAP(flags, __IECM_VPORT_FLAGS_NBITS);
> +
> +	/* RX */
> +	int num_rxq;
> +	int num_bufq;
> +	int rxq_desc_count;
> +	u8 num_bufqs_per_qgrp;
> +	int bufq_desc_count[IECM_MAX_BUFQS_PER_RXQ_GRP];
> +	u32 bufq_size[IECM_MAX_BUFQS_PER_RXQ_GRP];
> +	int num_rxq_grp;
> +	struct iecm_rxq_group *rxq_grps;
> +	u32 rxq_model;
> +
> +	struct iecm_adapter *adapter;
> +	struct net_device *netdev;
> +	u16 vport_type;
> +	u16 vport_id;
> +	u16 idx;		 /* software index in adapter vports struct */
> +	bool base_rxd;

Bools are not really advised to use inside structures since they may
have different sizes and alignments. There's a 2-byte hole here, so
u8 or u16 for base_rxd would do the job.

> +
> +	/* handler for hard interrupt */
> +	irqreturn_t (*irq_q_handler)(int irq, void *data);
> +	struct iecm_q_vector *q_vectors;	/* q vector array */
> +	u16 num_q_vectors;
> +	u16 q_vector_base;
> +	u16 max_mtu;
> +	u8 default_mac_addr[ETH_ALEN];
> +	u16 qset_handle;
> +	/* ITR profiles for the DIM algorithm */
> +#define IECM_DIM_PROFILE_SLOTS	5
> +	u16 rx_itr_profile[IECM_DIM_PROFILE_SLOTS];
> +	u16 tx_itr_profile[IECM_DIM_PROFILE_SLOTS];
> +	struct rtnl_link_stats64 netstats;
> +	struct iecm_port_stats port_stats;
> +
> +	/* lock to protect against multiple stop threads, which can happen when
> +	 * the driver is in a namespace in a system that is being shutdown
> +	 */
> +	struct mutex stop_mutex;
>  };
>  
>  enum iecm_user_flags {
> @@ -164,6 +424,7 @@ struct iecm_adapter {
>  	u16 num_msix_entries;
>  	struct msix_entry *msix_entries;
>  	struct virtchnl2_alloc_vectors *req_vec_chunks;
> +	struct iecm_q_vector mb_vector;
>  
>  	/* vport structs */
>  	struct iecm_vport **vports;	/* vports created by the driver */
> @@ -190,6 +451,8 @@ struct iecm_adapter {
>  
>  	wait_queue_head_t vchnl_wq;
>  	wait_queue_head_t sw_marker_wq;
> +	DECLARE_BITMAP(vc_state, IECM_VC_NBITS);
> +	char vc_msg[IECM_DFLT_MBX_BUF_SIZE];
>  	struct iecm_rss_data rss_data;
>  	struct iecm_dev_ops dev_ops;
>  	s32 link_speed;
> @@ -215,6 +478,38 @@ struct iecm_adapter {
>  	spinlock_t fdir_fltr_list_lock;
>  };
>  
> +/**
> + * iecm_is_queue_model_split - check if queue model is split
> + * @q_model: queue model single or split
> + *
> + * Returns true if queue model is split else false
> + */
> +static inline int iecm_is_queue_model_split(u16 q_model)
> +{
> +	return (q_model == VIRTCHNL2_QUEUE_MODEL_SPLIT);
> +}
> +
> +#define iecm_is_cap_ena(adapter, field, flag) \
> +	__iecm_is_cap_ena(adapter, false, field, flag)
> +#define iecm_is_cap_ena_all(adapter, field, flag) \
> +	__iecm_is_cap_ena(adapter, true, field, flag)
> +/**
> + * __iecm_is_cap_ena - Determine if HW capability is supported
> + * @adapter: private data struct
> + * @all: all or one flag
> + * @field: cap field to check
> + * @flag: Feature flag to check
> + *
> + * iecm_is_cap_ena_all is used to check if all the capability bits are set
> + * ('AND' operation) where as iecm_is_cap_ena is used to check if
> + * any one of the capability bits is set ('OR' operation)
> + */
> +static inline bool __iecm_is_cap_ena(struct iecm_adapter *adapter, bool all,
> +				     enum iecm_cap_field field, u64 flag)
> +{
> +	return adapter->dev_ops.vc_ops.is_cap_ena(adapter, all, field, flag);
> +}
> +
>  /**
>   * iecm_is_reset_detected - check if we were reset at some point
>   * @adapter: driver specific private structure
> @@ -233,6 +528,25 @@ int iecm_probe(struct pci_dev *pdev,
>  void iecm_remove(struct pci_dev *pdev);
>  int iecm_init_dflt_mbx(struct iecm_adapter *adapter);
>  void iecm_deinit_dflt_mbx(struct iecm_adapter *adapter);
> +void iecm_vc_ops_init(struct iecm_adapter *adapter);
> +int iecm_vc_core_init(struct iecm_adapter *adapter, int *vport_id);
> +int iecm_wait_for_event(struct iecm_adapter *adapter,
> +			enum iecm_vport_vc_state state,
> +			enum iecm_vport_vc_state err_check);
> +int iecm_min_wait_for_event(struct iecm_adapter *adapter,
> +			    enum iecm_vport_vc_state state,
> +			    enum iecm_vport_vc_state err_check);
> +int iecm_send_get_caps_msg(struct iecm_adapter *adapter);
>  int iecm_vport_params_buf_alloc(struct iecm_adapter *adapter);
>  void iecm_vport_params_buf_rel(struct iecm_adapter *adapter);
> +int iecm_get_vec_ids(struct iecm_adapter *adapter,
> +		     u16 *vecids, int num_vecids,
> +		     struct virtchnl2_vector_chunks *chunks);
> +int iecm_recv_mb_msg(struct iecm_adapter *adapter, enum virtchnl_ops op,
> +		     void *msg, int msg_size);
> +int iecm_send_mb_msg(struct iecm_adapter *adapter, enum virtchnl_ops op,
> +		     u16 msg_size, u8 *msg);
> +int iecm_set_msg_pending(struct iecm_adapter *adapter,
> +			 struct iecm_ctlq_msg *ctlq_msg,
> +			 enum iecm_vport_vc_state err_enum);
>  #endif /* !_IECM_H_ */
> diff --git a/drivers/net/ethernet/intel/include/iecm_txrx.h b/drivers/net/ethernet/intel/include/iecm_txrx.h
> index 602d3b3b19dd..e1348011c991 100644
> --- a/drivers/net/ethernet/intel/include/iecm_txrx.h
> +++ b/drivers/net/ethernet/intel/include/iecm_txrx.h
> @@ -30,4 +30,98 @@
>  #define IECM_DFLT_SPLITQ_RX_Q_GROUPS		4
>  #define IECM_DFLT_SPLITQ_TXQ_PER_GROUP		1
>  #define IECM_DFLT_SPLITQ_RXQ_PER_GROUP		1
> +
> +/* Default vector sharing */
> +#define IECM_NONQ_VEC		1
> +#define IECM_MAX_Q_VEC		4 /* For Tx Completion queue and Rx queue */
> +#define IECM_MIN_Q_VEC		1
> +#define IECM_MAX_RDMA_VEC	2 /* To share with RDMA */
> +#define IECM_MIN_RDMA_VEC	1 /* Minimum vectors to be shared with RDMA */
> +#define IECM_MIN_VEC		3 /* One for mailbox, one for data queues, one
> +				   * for RDMA
> +				   */
> +
> +#define IECM_DFLT_TX_Q_DESC_COUNT		512
> +#define IECM_DFLT_TX_COMPLQ_DESC_COUNT		512
> +#define IECM_DFLT_RX_Q_DESC_COUNT		512
> +/* IMPORTANT: We absolutely _cannot_ have more buffers in the system than a
> + * given RX completion queue has descriptors. This includes _ALL_ buffer
> + * queues. E.g.: If you have two buffer queues of 512 descriptors and buffers,
> + * you have a total of 1024 buffers so your RX queue _must_ have at least that
> + * many descriptors. This macro divides a given number of RX descriptors by
> + * number of buffer queues to calculate how many descriptors each buffer queue
> + * can have without overrunning the RX queue.
> + *
> + * If you give hardware more buffers than completion descriptors what will
> + * happen is that if hardware gets a chance to post more than ring wrap of
> + * descriptors before SW gets an interrupt and overwrites SW head, the gen bit
> + * in the descriptor will be wrong. Any overwritten descriptors' buffers will
> + * be gone forever and SW has no reasonable way to tell that this has happened.
> + * From SW perspective, when we finally get an interrupt, it looks like we're
> + * still waiting for descriptor to be done, stalling forever.
> + */
> +#define IECM_RX_BUFQ_DESC_COUNT(RXD, NUM_BUFQ)	((RXD) / (NUM_BUFQ))
> +
> +#define IECM_RX_BUFQ_WORKING_SET(R)		((R)->desc_count - 1)
> +#define IECM_RX_BUFQ_NON_WORKING_SET(R)		((R)->desc_count - \
> +						 IECM_RX_BUFQ_WORKING_SET(R))
> +
> +#define IECM_RX_HDR_SIZE			256
> +#define IECM_RX_BUF_2048			2048
> +#define IECM_RX_BUF_4096			4096
> +#define IECM_RX_BUF_STRIDE			64
> +#define IECM_LOW_WATERMARK			64
> +#define IECM_HDR_BUF_SIZE			256
> +#define IECM_PACKET_HDR_PAD	\
> +	(ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2))
> +#define IECM_MAX_RXBUFFER			9728
> +#define IECM_MAX_MTU		\
> +	(IECM_MAX_RXBUFFER - IECM_PACKET_HDR_PAD)
> +#define IECM_INT_NAME_STR_LEN	(IFNAMSIZ + 16)
> +
> +#define IECM_TX_COMPLQ_CLEAN_BUDGET	256
> +
> +struct iecm_intr_reg {
> +	u32 dyn_ctl;
> +	u32 dyn_ctl_intena_m;
> +	u32 dyn_ctl_clrpba_m;
> +	u32 dyn_ctl_itridx_s;
> +	u32 dyn_ctl_itridx_m;
> +	u32 dyn_ctl_intrvl_s;
> +	u32 rx_itr;
> +	u32 tx_itr;
> +	u32 icr_ena;
> +	u32 icr_ena_ctlq_m;
> +};
> +
> +struct iecm_q_vector {
> +	struct iecm_vport *vport;
> +	cpumask_t affinity_mask;
> +	struct napi_struct napi;
> +	u16 v_idx;		/* index in the vport->q_vector array */
> +	struct iecm_intr_reg intr_reg;
> +
> +	int num_txq;
> +	struct iecm_queue **tx;
> +	struct dim tx_dim;	/* data for net_dim algorithm */
> +	u16 tx_itr_value;
> +	bool tx_intr_mode;

Same here.

> +	u32 tx_itr_idx;
> +
> +	int num_rxq;
> +	struct iecm_queue **rx;
> +	struct dim rx_dim;	/* data for net_dim algorithm */
> +	u16 rx_itr_value;
> +	bool rx_intr_mode;

...here as well, and most likely in more places I overlooked.

> +	u32 rx_itr_idx;
> +
> +	int num_bufq;
> +	struct iecm_queue **bufq;
> +
> +	u16 total_events;       /* net_dim(): number of interrupts processed */
> +	char name[IECM_INT_NAME_STR_LEN];
> +};
> +
> +irqreturn_t
> +iecm_vport_intr_clean_queues(int __always_unused irq, void *data);
>  #endif /* !_IECM_TXRX_H_ */
> -- 
> 2.33.0

Thanks,
Al

  parent reply	other threads:[~2022-01-28 12:32 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 [this message]
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
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=20220128123244.21159-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