193f1cac5SPaul Winder /******************************************************************************
293f1cac5SPaul Winder 
3*df36e06dSRobert Mustacchi   Copyright (c) 2013-2018, Intel Corporation
493f1cac5SPaul Winder   All rights reserved.
593f1cac5SPaul Winder 
693f1cac5SPaul Winder   Redistribution and use in source and binary forms, with or without
793f1cac5SPaul Winder   modification, are permitted provided that the following conditions are met:
893f1cac5SPaul Winder 
993f1cac5SPaul Winder    1. Redistributions of source code must retain the above copyright notice,
1093f1cac5SPaul Winder       this list of conditions and the following disclaimer.
1193f1cac5SPaul Winder 
1293f1cac5SPaul Winder    2. Redistributions in binary form must reproduce the above copyright
1393f1cac5SPaul Winder       notice, this list of conditions and the following disclaimer in the
1493f1cac5SPaul Winder       documentation and/or other materials provided with the distribution.
1593f1cac5SPaul Winder 
1693f1cac5SPaul Winder    3. Neither the name of the Intel Corporation nor the names of its
1793f1cac5SPaul Winder       contributors may be used to endorse or promote products derived from
1893f1cac5SPaul Winder       this software without specific prior written permission.
1993f1cac5SPaul Winder 
2093f1cac5SPaul Winder   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2193f1cac5SPaul Winder   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2293f1cac5SPaul Winder   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2393f1cac5SPaul Winder   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2493f1cac5SPaul Winder   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2593f1cac5SPaul Winder   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2693f1cac5SPaul Winder   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2793f1cac5SPaul Winder   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2893f1cac5SPaul Winder   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2993f1cac5SPaul Winder   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3093f1cac5SPaul Winder   POSSIBILITY OF SUCH DAMAGE.
3193f1cac5SPaul Winder 
3293f1cac5SPaul Winder ******************************************************************************/
3393f1cac5SPaul Winder /*$FreeBSD$*/
3493f1cac5SPaul Winder 
3593f1cac5SPaul Winder #ifndef _VIRTCHNL_H_
3693f1cac5SPaul Winder #define _VIRTCHNL_H_
3793f1cac5SPaul Winder 
3893f1cac5SPaul Winder /* Description:
3993f1cac5SPaul Winder  * This header file describes the VF-PF communication protocol used
4093f1cac5SPaul Winder  * by the drivers for all devices starting from our 40G product line
4193f1cac5SPaul Winder  *
4293f1cac5SPaul Winder  * Admin queue buffer usage:
4393f1cac5SPaul Winder  * desc->opcode is always aqc_opc_send_msg_to_pf
4493f1cac5SPaul Winder  * flags, retval, datalen, and data addr are all used normally.
4593f1cac5SPaul Winder  * The Firmware copies the cookie fields when sending messages between the
4693f1cac5SPaul Winder  * PF and VF, but uses all other fields internally. Due to this limitation,
4793f1cac5SPaul Winder  * we must send all messages as "indirect", i.e. using an external buffer.
4893f1cac5SPaul Winder  *
4993f1cac5SPaul Winder  * All the VSI indexes are relative to the VF. Each VF can have maximum of
5093f1cac5SPaul Winder  * three VSIs. All the queue indexes are relative to the VSI.  Each VF can
5193f1cac5SPaul Winder  * have a maximum of sixteen queues for all of its VSIs.
5293f1cac5SPaul Winder  *
5393f1cac5SPaul Winder  * The PF is required to return a status code in v_retval for all messages
5493f1cac5SPaul Winder  * except RESET_VF, which does not require any response. The return value
5593f1cac5SPaul Winder  * is of status_code type, defined in the shared type.h.
5693f1cac5SPaul Winder  *
5793f1cac5SPaul Winder  * In general, VF driver initialization should roughly follow the order of
5893f1cac5SPaul Winder  * these opcodes. The VF driver must first validate the API version of the
5993f1cac5SPaul Winder  * PF driver, then request a reset, then get resources, then configure
6093f1cac5SPaul Winder  * queues and interrupts. After these operations are complete, the VF
6193f1cac5SPaul Winder  * driver may start its queues, optionally add MAC and VLAN filters, and
6293f1cac5SPaul Winder  * process traffic.
6393f1cac5SPaul Winder  */
6493f1cac5SPaul Winder 
6593f1cac5SPaul Winder /* START GENERIC DEFINES
6693f1cac5SPaul Winder  * Need to ensure the following enums and defines hold the same meaning and
6793f1cac5SPaul Winder  * value in current and future projects
6893f1cac5SPaul Winder  */
6993f1cac5SPaul Winder 
7093f1cac5SPaul Winder /* Error Codes */
7193f1cac5SPaul Winder enum virtchnl_status_code {
7293f1cac5SPaul Winder 	VIRTCHNL_STATUS_SUCCESS				= 0,
7393f1cac5SPaul Winder 	VIRTCHNL_ERR_PARAM				= -5,
7493f1cac5SPaul Winder 	VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH		= -38,
7593f1cac5SPaul Winder 	VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR		= -39,
7693f1cac5SPaul Winder 	VIRTCHNL_STATUS_ERR_INVALID_VF_ID		= -40,
7793f1cac5SPaul Winder 	VIRTCHNL_STATUS_NOT_SUPPORTED			= -64,
7893f1cac5SPaul Winder };
7993f1cac5SPaul Winder 
80*df36e06dSRobert Mustacchi #define VIRTCHNL_LINK_SPEED_2_5GB_SHIFT		0x0
8193f1cac5SPaul Winder #define VIRTCHNL_LINK_SPEED_100MB_SHIFT		0x1
8293f1cac5SPaul Winder #define VIRTCHNL_LINK_SPEED_1000MB_SHIFT	0x2
8393f1cac5SPaul Winder #define VIRTCHNL_LINK_SPEED_10GB_SHIFT		0x3
8493f1cac5SPaul Winder #define VIRTCHNL_LINK_SPEED_40GB_SHIFT		0x4
8593f1cac5SPaul Winder #define VIRTCHNL_LINK_SPEED_20GB_SHIFT		0x5
8693f1cac5SPaul Winder #define VIRTCHNL_LINK_SPEED_25GB_SHIFT		0x6
87*df36e06dSRobert Mustacchi #define VIRTCHNL_LINK_SPEED_5GB_SHIFT		0x7
8893f1cac5SPaul Winder 
8993f1cac5SPaul Winder enum virtchnl_link_speed {
9093f1cac5SPaul Winder 	VIRTCHNL_LINK_SPEED_UNKNOWN	= 0,
9193f1cac5SPaul Winder 	VIRTCHNL_LINK_SPEED_100MB	= BIT(VIRTCHNL_LINK_SPEED_100MB_SHIFT),
9293f1cac5SPaul Winder 	VIRTCHNL_LINK_SPEED_1GB		= BIT(VIRTCHNL_LINK_SPEED_1000MB_SHIFT),
9393f1cac5SPaul Winder 	VIRTCHNL_LINK_SPEED_10GB	= BIT(VIRTCHNL_LINK_SPEED_10GB_SHIFT),
9493f1cac5SPaul Winder 	VIRTCHNL_LINK_SPEED_40GB	= BIT(VIRTCHNL_LINK_SPEED_40GB_SHIFT),
9593f1cac5SPaul Winder 	VIRTCHNL_LINK_SPEED_20GB	= BIT(VIRTCHNL_LINK_SPEED_20GB_SHIFT),
9693f1cac5SPaul Winder 	VIRTCHNL_LINK_SPEED_25GB	= BIT(VIRTCHNL_LINK_SPEED_25GB_SHIFT),
97*df36e06dSRobert Mustacchi 	VIRTCHNL_LINK_SPEED_2_5GB	= BIT(VIRTCHNL_LINK_SPEED_2_5GB_SHIFT),
98*df36e06dSRobert Mustacchi 	VIRTCHNL_LINK_SPEED_5GB		= BIT(VIRTCHNL_LINK_SPEED_5GB_SHIFT),
9993f1cac5SPaul Winder };
10093f1cac5SPaul Winder 
10193f1cac5SPaul Winder /* for hsplit_0 field of Rx HMC context */
10293f1cac5SPaul Winder /* deprecated with AVF 1.0 */
10393f1cac5SPaul Winder enum virtchnl_rx_hsplit {
10493f1cac5SPaul Winder 	VIRTCHNL_RX_HSPLIT_NO_SPLIT      = 0,
10593f1cac5SPaul Winder 	VIRTCHNL_RX_HSPLIT_SPLIT_L2      = 1,
10693f1cac5SPaul Winder 	VIRTCHNL_RX_HSPLIT_SPLIT_IP      = 2,
10793f1cac5SPaul Winder 	VIRTCHNL_RX_HSPLIT_SPLIT_TCP_UDP = 4,
10893f1cac5SPaul Winder 	VIRTCHNL_RX_HSPLIT_SPLIT_SCTP    = 8,
10993f1cac5SPaul Winder };
11093f1cac5SPaul Winder 
11193f1cac5SPaul Winder #define VIRTCHNL_ETH_LENGTH_OF_ADDRESS	6
11293f1cac5SPaul Winder /* END GENERIC DEFINES */
11393f1cac5SPaul Winder 
11493f1cac5SPaul Winder /* Opcodes for VF-PF communication. These are placed in the v_opcode field
11593f1cac5SPaul Winder  * of the virtchnl_msg structure.
11693f1cac5SPaul Winder  */
11793f1cac5SPaul Winder enum virtchnl_ops {
11893f1cac5SPaul Winder /* The PF sends status change events to VFs using
11993f1cac5SPaul Winder  * the VIRTCHNL_OP_EVENT opcode.
12093f1cac5SPaul Winder  * VFs send requests to the PF using the other ops.
12193f1cac5SPaul Winder  * Use of "advanced opcode" features must be negotiated as part of capabilities
12293f1cac5SPaul Winder  * exchange and are not considered part of base mode feature set.
12393f1cac5SPaul Winder  */
12493f1cac5SPaul Winder 	VIRTCHNL_OP_UNKNOWN = 0,
12593f1cac5SPaul Winder 	VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */
12693f1cac5SPaul Winder 	VIRTCHNL_OP_RESET_VF = 2,
12793f1cac5SPaul Winder 	VIRTCHNL_OP_GET_VF_RESOURCES = 3,
12893f1cac5SPaul Winder 	VIRTCHNL_OP_CONFIG_TX_QUEUE = 4,
12993f1cac5SPaul Winder 	VIRTCHNL_OP_CONFIG_RX_QUEUE = 5,
13093f1cac5SPaul Winder 	VIRTCHNL_OP_CONFIG_VSI_QUEUES = 6,
13193f1cac5SPaul Winder 	VIRTCHNL_OP_CONFIG_IRQ_MAP = 7,
13293f1cac5SPaul Winder 	VIRTCHNL_OP_ENABLE_QUEUES = 8,
13393f1cac5SPaul Winder 	VIRTCHNL_OP_DISABLE_QUEUES = 9,
13493f1cac5SPaul Winder 	VIRTCHNL_OP_ADD_ETH_ADDR = 10,
13593f1cac5SPaul Winder 	VIRTCHNL_OP_DEL_ETH_ADDR = 11,
13693f1cac5SPaul Winder 	VIRTCHNL_OP_ADD_VLAN = 12,
13793f1cac5SPaul Winder 	VIRTCHNL_OP_DEL_VLAN = 13,
13893f1cac5SPaul Winder 	VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14,
13993f1cac5SPaul Winder 	VIRTCHNL_OP_GET_STATS = 15,
14093f1cac5SPaul Winder 	VIRTCHNL_OP_RSVD = 16,
14193f1cac5SPaul Winder 	VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */
14293f1cac5SPaul Winder 	VIRTCHNL_OP_IWARP = 20, /* advanced opcode */
14393f1cac5SPaul Winder 	VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21, /* advanced opcode */
14493f1cac5SPaul Winder 	VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP = 22, /* advanced opcode */
14593f1cac5SPaul Winder 	VIRTCHNL_OP_CONFIG_RSS_KEY = 23,
14693f1cac5SPaul Winder 	VIRTCHNL_OP_CONFIG_RSS_LUT = 24,
14793f1cac5SPaul Winder 	VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25,
14893f1cac5SPaul Winder 	VIRTCHNL_OP_SET_RSS_HENA = 26,
14993f1cac5SPaul Winder 	VIRTCHNL_OP_ENABLE_VLAN_STRIPPING = 27,
15093f1cac5SPaul Winder 	VIRTCHNL_OP_DISABLE_VLAN_STRIPPING = 28,
15193f1cac5SPaul Winder 	VIRTCHNL_OP_REQUEST_QUEUES = 29,
15293f1cac5SPaul Winder 
15393f1cac5SPaul Winder };
15493f1cac5SPaul Winder 
15593f1cac5SPaul Winder /* This macro is used to generate a compilation error if a structure
15693f1cac5SPaul Winder  * is not exactly the correct length. It gives a divide by zero error if the
15793f1cac5SPaul Winder  * structure is not of the correct size, otherwise it creates an enum that is
15893f1cac5SPaul Winder  * never used.
15993f1cac5SPaul Winder  */
16093f1cac5SPaul Winder #define VIRTCHNL_CHECK_STRUCT_LEN(n, X) enum virtchnl_static_assert_enum_##X \
16193f1cac5SPaul Winder 	{virtchnl_static_assert_##X = (n) / ((sizeof(struct X) == (n)) ? 1 : 0)}
16293f1cac5SPaul Winder 
16393f1cac5SPaul Winder /* Virtual channel message descriptor. This overlays the admin queue
16493f1cac5SPaul Winder  * descriptor. All other data is passed in external buffers.
16593f1cac5SPaul Winder  */
16693f1cac5SPaul Winder 
16793f1cac5SPaul Winder struct virtchnl_msg {
16893f1cac5SPaul Winder 	u8 pad[8];			 /* AQ flags/opcode/len/retval fields */
16993f1cac5SPaul Winder 	enum virtchnl_ops v_opcode; /* avoid confusion with desc->opcode */
17093f1cac5SPaul Winder 	enum virtchnl_status_code v_retval;  /* ditto for desc->retval */
17193f1cac5SPaul Winder 	u32 vfid;			 /* used by PF when sending to VF */
17293f1cac5SPaul Winder };
17393f1cac5SPaul Winder 
17493f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(20, virtchnl_msg);
17593f1cac5SPaul Winder 
17693f1cac5SPaul Winder /* Message descriptions and data structures.*/
17793f1cac5SPaul Winder 
17893f1cac5SPaul Winder /* VIRTCHNL_OP_VERSION
17993f1cac5SPaul Winder  * VF posts its version number to the PF. PF responds with its version number
18093f1cac5SPaul Winder  * in the same format, along with a return code.
18193f1cac5SPaul Winder  * Reply from PF has its major/minor versions also in param0 and param1.
18293f1cac5SPaul Winder  * If there is a major version mismatch, then the VF cannot operate.
18393f1cac5SPaul Winder  * If there is a minor version mismatch, then the VF can operate but should
18493f1cac5SPaul Winder  * add a warning to the system log.
18593f1cac5SPaul Winder  *
18693f1cac5SPaul Winder  * This enum element MUST always be specified as == 1, regardless of other
18793f1cac5SPaul Winder  * changes in the API. The PF must always respond to this message without
18893f1cac5SPaul Winder  * error regardless of version mismatch.
18993f1cac5SPaul Winder  */
19093f1cac5SPaul Winder #define VIRTCHNL_VERSION_MAJOR		1
19193f1cac5SPaul Winder #define VIRTCHNL_VERSION_MINOR		1
19293f1cac5SPaul Winder #define VIRTCHNL_VERSION_MINOR_NO_VF_CAPS	0
19393f1cac5SPaul Winder 
19493f1cac5SPaul Winder struct virtchnl_version_info {
19593f1cac5SPaul Winder 	u32 major;
19693f1cac5SPaul Winder 	u32 minor;
19793f1cac5SPaul Winder };
19893f1cac5SPaul Winder 
19993f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_version_info);
20093f1cac5SPaul Winder 
20193f1cac5SPaul Winder #define VF_IS_V10(_v) (((_v)->major == 1) && ((_v)->minor == 0))
20293f1cac5SPaul Winder #define VF_IS_V11(_ver) (((_ver)->major == 1) && ((_ver)->minor == 1))
20393f1cac5SPaul Winder 
20493f1cac5SPaul Winder /* VIRTCHNL_OP_RESET_VF
20593f1cac5SPaul Winder  * VF sends this request to PF with no parameters
20693f1cac5SPaul Winder  * PF does NOT respond! VF driver must delay then poll VFGEN_RSTAT register
20793f1cac5SPaul Winder  * until reset completion is indicated. The admin queue must be reinitialized
20893f1cac5SPaul Winder  * after this operation.
20993f1cac5SPaul Winder  *
21093f1cac5SPaul Winder  * When reset is complete, PF must ensure that all queues in all VSIs associated
21193f1cac5SPaul Winder  * with the VF are stopped, all queue configurations in the HMC are set to 0,
21293f1cac5SPaul Winder  * and all MAC and VLAN filters (except the default MAC address) on all VSIs
21393f1cac5SPaul Winder  * are cleared.
21493f1cac5SPaul Winder  */
21593f1cac5SPaul Winder 
21693f1cac5SPaul Winder /* VSI types that use VIRTCHNL interface for VF-PF communication. VSI_SRIOV
21793f1cac5SPaul Winder  * vsi_type should always be 6 for backward compatibility. Add other fields
21893f1cac5SPaul Winder  * as needed.
21993f1cac5SPaul Winder  */
22093f1cac5SPaul Winder enum virtchnl_vsi_type {
22193f1cac5SPaul Winder 	VIRTCHNL_VSI_TYPE_INVALID = 0,
22293f1cac5SPaul Winder 	VIRTCHNL_VSI_SRIOV = 6,
22393f1cac5SPaul Winder };
22493f1cac5SPaul Winder 
22593f1cac5SPaul Winder /* VIRTCHNL_OP_GET_VF_RESOURCES
22693f1cac5SPaul Winder  * Version 1.0 VF sends this request to PF with no parameters
22793f1cac5SPaul Winder  * Version 1.1 VF sends this request to PF with u32 bitmap of its capabilities
22893f1cac5SPaul Winder  * PF responds with an indirect message containing
22993f1cac5SPaul Winder  * virtchnl_vf_resource and one or more
23093f1cac5SPaul Winder  * virtchnl_vsi_resource structures.
23193f1cac5SPaul Winder  */
23293f1cac5SPaul Winder 
23393f1cac5SPaul Winder struct virtchnl_vsi_resource {
23493f1cac5SPaul Winder 	u16 vsi_id;
23593f1cac5SPaul Winder 	u16 num_queue_pairs;
23693f1cac5SPaul Winder 	enum virtchnl_vsi_type vsi_type;
23793f1cac5SPaul Winder 	u16 qset_handle;
23893f1cac5SPaul Winder 	u8 default_mac_addr[VIRTCHNL_ETH_LENGTH_OF_ADDRESS];
23993f1cac5SPaul Winder };
24093f1cac5SPaul Winder 
24193f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource);
24293f1cac5SPaul Winder 
24393f1cac5SPaul Winder /* VF capability flags
24493f1cac5SPaul Winder  * VIRTCHNL_VF_OFFLOAD_L2 flag is inclusive of base mode L2 offloads including
24593f1cac5SPaul Winder  * TX/RX Checksum offloading and TSO for non-tunnelled packets.
24693f1cac5SPaul Winder  */
24793f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_L2			0x00000001
24893f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_IWARP		0x00000002
24993f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_RSVD		0x00000004
25093f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_RSS_AQ		0x00000008
25193f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_RSS_REG		0x00000010
25293f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_WB_ON_ITR		0x00000020
25393f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_REQ_QUEUES		0x00000040
25493f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_VLAN		0x00010000
25593f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_RX_POLLING		0x00020000
25693f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2	0x00040000
25793f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_RSS_PF		0X00080000
25893f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_ENCAP		0X00100000
25993f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM		0X00200000
26093f1cac5SPaul Winder #define VIRTCHNL_VF_OFFLOAD_RX_ENCAP_CSUM	0X00400000
26193f1cac5SPaul Winder 
26293f1cac5SPaul Winder #define VF_BASE_MODE_OFFLOADS (VIRTCHNL_VF_OFFLOAD_L2 | \
26393f1cac5SPaul Winder 			       VIRTCHNL_VF_OFFLOAD_VLAN | \
26493f1cac5SPaul Winder 			       VIRTCHNL_VF_OFFLOAD_RSS_PF)
26593f1cac5SPaul Winder 
26693f1cac5SPaul Winder struct virtchnl_vf_resource {
26793f1cac5SPaul Winder 	u16 num_vsis;
26893f1cac5SPaul Winder 	u16 num_queue_pairs;
26993f1cac5SPaul Winder 	u16 max_vectors;
27093f1cac5SPaul Winder 	u16 max_mtu;
27193f1cac5SPaul Winder 
27293f1cac5SPaul Winder 	u32 vf_cap_flags;
27393f1cac5SPaul Winder 	u32 rss_key_size;
27493f1cac5SPaul Winder 	u32 rss_lut_size;
27593f1cac5SPaul Winder 
27693f1cac5SPaul Winder 	struct virtchnl_vsi_resource vsi_res[1];
27793f1cac5SPaul Winder };
27893f1cac5SPaul Winder 
27993f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(36, virtchnl_vf_resource);
28093f1cac5SPaul Winder 
28193f1cac5SPaul Winder /* VIRTCHNL_OP_CONFIG_TX_QUEUE
28293f1cac5SPaul Winder  * VF sends this message to set up parameters for one TX queue.
28393f1cac5SPaul Winder  * External data buffer contains one instance of virtchnl_txq_info.
28493f1cac5SPaul Winder  * PF configures requested queue and returns a status code.
28593f1cac5SPaul Winder  */
28693f1cac5SPaul Winder 
28793f1cac5SPaul Winder /* Tx queue config info */
28893f1cac5SPaul Winder struct virtchnl_txq_info {
28993f1cac5SPaul Winder 	u16 vsi_id;
29093f1cac5SPaul Winder 	u16 queue_id;
29193f1cac5SPaul Winder 	u16 ring_len;		/* number of descriptors, multiple of 8 */
29293f1cac5SPaul Winder 	u16 headwb_enabled; /* deprecated with AVF 1.0 */
29393f1cac5SPaul Winder 	u64 dma_ring_addr;
29493f1cac5SPaul Winder 	u64 dma_headwb_addr; /* deprecated with AVF 1.0 */
29593f1cac5SPaul Winder };
29693f1cac5SPaul Winder 
29793f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_txq_info);
29893f1cac5SPaul Winder 
29993f1cac5SPaul Winder /* VIRTCHNL_OP_CONFIG_RX_QUEUE
30093f1cac5SPaul Winder  * VF sends this message to set up parameters for one RX queue.
30193f1cac5SPaul Winder  * External data buffer contains one instance of virtchnl_rxq_info.
30293f1cac5SPaul Winder  * PF configures requested queue and returns a status code.
30393f1cac5SPaul Winder  */
30493f1cac5SPaul Winder 
30593f1cac5SPaul Winder /* Rx queue config info */
30693f1cac5SPaul Winder struct virtchnl_rxq_info {
30793f1cac5SPaul Winder 	u16 vsi_id;
30893f1cac5SPaul Winder 	u16 queue_id;
30993f1cac5SPaul Winder 	u32 ring_len;		/* number of descriptors, multiple of 32 */
31093f1cac5SPaul Winder 	u16 hdr_size;
31193f1cac5SPaul Winder 	u16 splithdr_enabled; /* deprecated with AVF 1.0 */
31293f1cac5SPaul Winder 	u32 databuffer_size;
31393f1cac5SPaul Winder 	u32 max_pkt_size;
31493f1cac5SPaul Winder 	u32 pad1;
31593f1cac5SPaul Winder 	u64 dma_ring_addr;
31693f1cac5SPaul Winder 	enum virtchnl_rx_hsplit rx_split_pos; /* deprecated with AVF 1.0 */
31793f1cac5SPaul Winder 	u32 pad2;
31893f1cac5SPaul Winder };
31993f1cac5SPaul Winder 
32093f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(40, virtchnl_rxq_info);
32193f1cac5SPaul Winder 
32293f1cac5SPaul Winder /* VIRTCHNL_OP_CONFIG_VSI_QUEUES
32393f1cac5SPaul Winder  * VF sends this message to set parameters for all active TX and RX queues
32493f1cac5SPaul Winder  * associated with the specified VSI.
32593f1cac5SPaul Winder  * PF configures queues and returns status.
32693f1cac5SPaul Winder  * If the number of queues specified is greater than the number of queues
32793f1cac5SPaul Winder  * associated with the VSI, an error is returned and no queues are configured.
32893f1cac5SPaul Winder  */
32993f1cac5SPaul Winder struct virtchnl_queue_pair_info {
33093f1cac5SPaul Winder 	/* NOTE: vsi_id and queue_id should be identical for both queues. */
33193f1cac5SPaul Winder 	struct virtchnl_txq_info txq;
33293f1cac5SPaul Winder 	struct virtchnl_rxq_info rxq;
33393f1cac5SPaul Winder };
33493f1cac5SPaul Winder 
33593f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(64, virtchnl_queue_pair_info);
33693f1cac5SPaul Winder 
33793f1cac5SPaul Winder struct virtchnl_vsi_queue_config_info {
33893f1cac5SPaul Winder 	u16 vsi_id;
33993f1cac5SPaul Winder 	u16 num_queue_pairs;
34093f1cac5SPaul Winder 	u32 pad;
34193f1cac5SPaul Winder 	struct virtchnl_queue_pair_info qpair[1];
34293f1cac5SPaul Winder };
34393f1cac5SPaul Winder 
34493f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(72, virtchnl_vsi_queue_config_info);
34593f1cac5SPaul Winder 
34693f1cac5SPaul Winder /* VIRTCHNL_OP_REQUEST_QUEUES
34793f1cac5SPaul Winder  * VF sends this message to request the PF to allocate additional queues to
34893f1cac5SPaul Winder  * this VF.  Each VF gets a guaranteed number of queues on init but asking for
34993f1cac5SPaul Winder  * additional queues must be negotiated.  This is a best effort request as it
35093f1cac5SPaul Winder  * is possible the PF does not have enough queues left to support the request.
35193f1cac5SPaul Winder  * If the PF cannot support the number requested it will respond with the
35293f1cac5SPaul Winder  * maximum number it is able to support; otherwise it will respond with the
35393f1cac5SPaul Winder  * number requested.
35493f1cac5SPaul Winder  */
35593f1cac5SPaul Winder 
35693f1cac5SPaul Winder /* VF resource request */
35793f1cac5SPaul Winder struct virtchnl_vf_res_request {
35893f1cac5SPaul Winder 	u16 num_queue_pairs;
35993f1cac5SPaul Winder };
36093f1cac5SPaul Winder 
36193f1cac5SPaul Winder /* VIRTCHNL_OP_CONFIG_IRQ_MAP
36293f1cac5SPaul Winder  * VF uses this message to map vectors to queues.
36393f1cac5SPaul Winder  * The rxq_map and txq_map fields are bitmaps used to indicate which queues
36493f1cac5SPaul Winder  * are to be associated with the specified vector.
36593f1cac5SPaul Winder  * The "other" causes are always mapped to vector 0.
36693f1cac5SPaul Winder  * PF configures interrupt mapping and returns status.
36793f1cac5SPaul Winder  */
36893f1cac5SPaul Winder struct virtchnl_vector_map {
36993f1cac5SPaul Winder 	u16 vsi_id;
37093f1cac5SPaul Winder 	u16 vector_id;
37193f1cac5SPaul Winder 	u16 rxq_map;
37293f1cac5SPaul Winder 	u16 txq_map;
37393f1cac5SPaul Winder 	u16 rxitr_idx;
37493f1cac5SPaul Winder 	u16 txitr_idx;
37593f1cac5SPaul Winder };
37693f1cac5SPaul Winder 
37793f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_vector_map);
37893f1cac5SPaul Winder 
37993f1cac5SPaul Winder struct virtchnl_irq_map_info {
38093f1cac5SPaul Winder 	u16 num_vectors;
38193f1cac5SPaul Winder 	struct virtchnl_vector_map vecmap[1];
38293f1cac5SPaul Winder };
38393f1cac5SPaul Winder 
38493f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(14, virtchnl_irq_map_info);
38593f1cac5SPaul Winder 
38693f1cac5SPaul Winder /* VIRTCHNL_OP_ENABLE_QUEUES
38793f1cac5SPaul Winder  * VIRTCHNL_OP_DISABLE_QUEUES
38893f1cac5SPaul Winder  * VF sends these message to enable or disable TX/RX queue pairs.
38993f1cac5SPaul Winder  * The queues fields are bitmaps indicating which queues to act upon.
39093f1cac5SPaul Winder  * (Currently, we only support 16 queues per VF, but we make the field
39193f1cac5SPaul Winder  * u32 to allow for expansion.)
39293f1cac5SPaul Winder  * PF performs requested action and returns status.
39393f1cac5SPaul Winder  */
39493f1cac5SPaul Winder struct virtchnl_queue_select {
39593f1cac5SPaul Winder 	u16 vsi_id;
39693f1cac5SPaul Winder 	u16 pad;
39793f1cac5SPaul Winder 	u32 rx_queues;
39893f1cac5SPaul Winder 	u32 tx_queues;
39993f1cac5SPaul Winder };
40093f1cac5SPaul Winder 
40193f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_queue_select);
40293f1cac5SPaul Winder 
40393f1cac5SPaul Winder /* VIRTCHNL_OP_ADD_ETH_ADDR
40493f1cac5SPaul Winder  * VF sends this message in order to add one or more unicast or multicast
40593f1cac5SPaul Winder  * address filters for the specified VSI.
40693f1cac5SPaul Winder  * PF adds the filters and returns status.
40793f1cac5SPaul Winder  */
40893f1cac5SPaul Winder 
40993f1cac5SPaul Winder /* VIRTCHNL_OP_DEL_ETH_ADDR
41093f1cac5SPaul Winder  * VF sends this message in order to remove one or more unicast or multicast
41193f1cac5SPaul Winder  * filters for the specified VSI.
41293f1cac5SPaul Winder  * PF removes the filters and returns status.
41393f1cac5SPaul Winder  */
41493f1cac5SPaul Winder 
41593f1cac5SPaul Winder struct virtchnl_ether_addr {
41693f1cac5SPaul Winder 	u8 addr[VIRTCHNL_ETH_LENGTH_OF_ADDRESS];
41793f1cac5SPaul Winder 	u8 pad[2];
41893f1cac5SPaul Winder };
41993f1cac5SPaul Winder 
42093f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_ether_addr);
42193f1cac5SPaul Winder 
42293f1cac5SPaul Winder struct virtchnl_ether_addr_list {
42393f1cac5SPaul Winder 	u16 vsi_id;
42493f1cac5SPaul Winder 	u16 num_elements;
42593f1cac5SPaul Winder 	struct virtchnl_ether_addr list[1];
42693f1cac5SPaul Winder };
42793f1cac5SPaul Winder 
42893f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_ether_addr_list);
42993f1cac5SPaul Winder 
43093f1cac5SPaul Winder /* VIRTCHNL_OP_ADD_VLAN
43193f1cac5SPaul Winder  * VF sends this message to add one or more VLAN tag filters for receives.
43293f1cac5SPaul Winder  * PF adds the filters and returns status.
43393f1cac5SPaul Winder  * If a port VLAN is configured by the PF, this operation will return an
43493f1cac5SPaul Winder  * error to the VF.
43593f1cac5SPaul Winder  */
43693f1cac5SPaul Winder 
43793f1cac5SPaul Winder /* VIRTCHNL_OP_DEL_VLAN
43893f1cac5SPaul Winder  * VF sends this message to remove one or more VLAN tag filters for receives.
43993f1cac5SPaul Winder  * PF removes the filters and returns status.
44093f1cac5SPaul Winder  * If a port VLAN is configured by the PF, this operation will return an
44193f1cac5SPaul Winder  * error to the VF.
44293f1cac5SPaul Winder  */
44393f1cac5SPaul Winder 
44493f1cac5SPaul Winder struct virtchnl_vlan_filter_list {
44593f1cac5SPaul Winder 	u16 vsi_id;
44693f1cac5SPaul Winder 	u16 num_elements;
44793f1cac5SPaul Winder 	u16 vlan_id[1];
44893f1cac5SPaul Winder };
44993f1cac5SPaul Winder 
45093f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_vlan_filter_list);
45193f1cac5SPaul Winder 
45293f1cac5SPaul Winder /* VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE
45393f1cac5SPaul Winder  * VF sends VSI id and flags.
45493f1cac5SPaul Winder  * PF returns status code in retval.
45593f1cac5SPaul Winder  * Note: we assume that broadcast accept mode is always enabled.
45693f1cac5SPaul Winder  */
45793f1cac5SPaul Winder struct virtchnl_promisc_info {
45893f1cac5SPaul Winder 	u16 vsi_id;
45993f1cac5SPaul Winder 	u16 flags;
46093f1cac5SPaul Winder };
46193f1cac5SPaul Winder 
46293f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(4, virtchnl_promisc_info);
46393f1cac5SPaul Winder 
46493f1cac5SPaul Winder #define FLAG_VF_UNICAST_PROMISC	0x00000001
46593f1cac5SPaul Winder #define FLAG_VF_MULTICAST_PROMISC	0x00000002
46693f1cac5SPaul Winder 
46793f1cac5SPaul Winder /* VIRTCHNL_OP_GET_STATS
46893f1cac5SPaul Winder  * VF sends this message to request stats for the selected VSI. VF uses
46993f1cac5SPaul Winder  * the virtchnl_queue_select struct to specify the VSI. The queue_id
47093f1cac5SPaul Winder  * field is ignored by the PF.
47193f1cac5SPaul Winder  *
47293f1cac5SPaul Winder  * PF replies with struct eth_stats in an external buffer.
47393f1cac5SPaul Winder  */
47493f1cac5SPaul Winder 
47593f1cac5SPaul Winder /* VIRTCHNL_OP_CONFIG_RSS_KEY
47693f1cac5SPaul Winder  * VIRTCHNL_OP_CONFIG_RSS_LUT
47793f1cac5SPaul Winder  * VF sends these messages to configure RSS. Only supported if both PF
47893f1cac5SPaul Winder  * and VF drivers set the VIRTCHNL_VF_OFFLOAD_RSS_PF bit during
47993f1cac5SPaul Winder  * configuration negotiation. If this is the case, then the RSS fields in
48093f1cac5SPaul Winder  * the VF resource struct are valid.
48193f1cac5SPaul Winder  * Both the key and LUT are initialized to 0 by the PF, meaning that
48293f1cac5SPaul Winder  * RSS is effectively disabled until set up by the VF.
48393f1cac5SPaul Winder  */
48493f1cac5SPaul Winder struct virtchnl_rss_key {
48593f1cac5SPaul Winder 	u16 vsi_id;
48693f1cac5SPaul Winder 	u16 key_len;
48793f1cac5SPaul Winder 	u8 key[1];         /* RSS hash key, packed bytes */
48893f1cac5SPaul Winder };
48993f1cac5SPaul Winder 
49093f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_key);
49193f1cac5SPaul Winder 
49293f1cac5SPaul Winder struct virtchnl_rss_lut {
49393f1cac5SPaul Winder 	u16 vsi_id;
49493f1cac5SPaul Winder 	u16 lut_entries;
49593f1cac5SPaul Winder 	u8 lut[1];        /* RSS lookup table */
49693f1cac5SPaul Winder };
49793f1cac5SPaul Winder 
49893f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_lut);
49993f1cac5SPaul Winder 
50093f1cac5SPaul Winder /* VIRTCHNL_OP_GET_RSS_HENA_CAPS
50193f1cac5SPaul Winder  * VIRTCHNL_OP_SET_RSS_HENA
50293f1cac5SPaul Winder  * VF sends these messages to get and set the hash filter enable bits for RSS.
50393f1cac5SPaul Winder  * By default, the PF sets these to all possible traffic types that the
50493f1cac5SPaul Winder  * hardware supports. The VF can query this value if it wants to change the
50593f1cac5SPaul Winder  * traffic types that are hashed by the hardware.
50693f1cac5SPaul Winder  */
50793f1cac5SPaul Winder struct virtchnl_rss_hena {
50893f1cac5SPaul Winder 	u64 hena;
50993f1cac5SPaul Winder };
51093f1cac5SPaul Winder 
51193f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_rss_hena);
51293f1cac5SPaul Winder 
51393f1cac5SPaul Winder /* VIRTCHNL_OP_EVENT
51493f1cac5SPaul Winder  * PF sends this message to inform the VF driver of events that may affect it.
51593f1cac5SPaul Winder  * No direct response is expected from the VF, though it may generate other
51693f1cac5SPaul Winder  * messages in response to this one.
51793f1cac5SPaul Winder  */
51893f1cac5SPaul Winder enum virtchnl_event_codes {
51993f1cac5SPaul Winder 	VIRTCHNL_EVENT_UNKNOWN = 0,
52093f1cac5SPaul Winder 	VIRTCHNL_EVENT_LINK_CHANGE,
52193f1cac5SPaul Winder 	VIRTCHNL_EVENT_RESET_IMPENDING,
52293f1cac5SPaul Winder 	VIRTCHNL_EVENT_PF_DRIVER_CLOSE,
52393f1cac5SPaul Winder };
52493f1cac5SPaul Winder 
52593f1cac5SPaul Winder #define PF_EVENT_SEVERITY_INFO		0
52693f1cac5SPaul Winder #define PF_EVENT_SEVERITY_ATTENTION	1
52793f1cac5SPaul Winder #define PF_EVENT_SEVERITY_ACTION_REQUIRED	2
52893f1cac5SPaul Winder #define PF_EVENT_SEVERITY_CERTAIN_DOOM	255
52993f1cac5SPaul Winder 
53093f1cac5SPaul Winder struct virtchnl_pf_event {
53193f1cac5SPaul Winder 	enum virtchnl_event_codes event;
53293f1cac5SPaul Winder 	union {
53393f1cac5SPaul Winder 		struct {
53493f1cac5SPaul Winder 			enum virtchnl_link_speed link_speed;
53593f1cac5SPaul Winder 			bool link_status;
53693f1cac5SPaul Winder 		} link_event;
53793f1cac5SPaul Winder 	} event_data;
53893f1cac5SPaul Winder 
53993f1cac5SPaul Winder 	int severity;
54093f1cac5SPaul Winder };
54193f1cac5SPaul Winder 
54293f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_pf_event);
54393f1cac5SPaul Winder 
54493f1cac5SPaul Winder 
54593f1cac5SPaul Winder /* VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP
54693f1cac5SPaul Winder  * VF uses this message to request PF to map IWARP vectors to IWARP queues.
54793f1cac5SPaul Winder  * The request for this originates from the VF IWARP driver through
54893f1cac5SPaul Winder  * a client interface between VF LAN and VF IWARP driver.
54993f1cac5SPaul Winder  * A vector could have an AEQ and CEQ attached to it although
55093f1cac5SPaul Winder  * there is a single AEQ per VF IWARP instance in which case
55193f1cac5SPaul Winder  * most vectors will have an INVALID_IDX for aeq and valid idx for ceq.
55293f1cac5SPaul Winder  * There will never be a case where there will be multiple CEQs attached
55393f1cac5SPaul Winder  * to a single vector.
55493f1cac5SPaul Winder  * PF configures interrupt mapping and returns status.
55593f1cac5SPaul Winder  */
55693f1cac5SPaul Winder 
55793f1cac5SPaul Winder /* HW does not define a type value for AEQ; only for RX/TX and CEQ.
55893f1cac5SPaul Winder  * In order for us to keep the interface simple, SW will define a
55993f1cac5SPaul Winder  * unique type value for AEQ.
56093f1cac5SPaul Winder  */
56193f1cac5SPaul Winder #define QUEUE_TYPE_PE_AEQ  0x80
56293f1cac5SPaul Winder #define QUEUE_INVALID_IDX  0xFFFF
56393f1cac5SPaul Winder 
56493f1cac5SPaul Winder struct virtchnl_iwarp_qv_info {
56593f1cac5SPaul Winder 	u32 v_idx; /* msix_vector */
56693f1cac5SPaul Winder 	u16 ceq_idx;
56793f1cac5SPaul Winder 	u16 aeq_idx;
56893f1cac5SPaul Winder 	u8 itr_idx;
56993f1cac5SPaul Winder };
57093f1cac5SPaul Winder 
57193f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_iwarp_qv_info);
57293f1cac5SPaul Winder 
57393f1cac5SPaul Winder struct virtchnl_iwarp_qvlist_info {
57493f1cac5SPaul Winder 	u32 num_vectors;
57593f1cac5SPaul Winder 	struct virtchnl_iwarp_qv_info qv_info[1];
57693f1cac5SPaul Winder };
57793f1cac5SPaul Winder 
57893f1cac5SPaul Winder VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_iwarp_qvlist_info);
57993f1cac5SPaul Winder 
58093f1cac5SPaul Winder 
58193f1cac5SPaul Winder /* VF reset states - these are written into the RSTAT register:
58293f1cac5SPaul Winder  * VFGEN_RSTAT on the VF
58393f1cac5SPaul Winder  * When the PF initiates a reset, it writes 0
58493f1cac5SPaul Winder  * When the reset is complete, it writes 1
58593f1cac5SPaul Winder  * When the PF detects that the VF has recovered, it writes 2
58693f1cac5SPaul Winder  * VF checks this register periodically to determine if a reset has occurred,
58793f1cac5SPaul Winder  * then polls it to know when the reset is complete.
58893f1cac5SPaul Winder  * If either the PF or VF reads the register while the hardware
58993f1cac5SPaul Winder  * is in a reset state, it will return DEADBEEF, which, when masked
59093f1cac5SPaul Winder  * will result in 3.
59193f1cac5SPaul Winder  */
59293f1cac5SPaul Winder enum virtchnl_vfr_states {
59393f1cac5SPaul Winder 	VIRTCHNL_VFR_INPROGRESS = 0,
59493f1cac5SPaul Winder 	VIRTCHNL_VFR_COMPLETED,
59593f1cac5SPaul Winder 	VIRTCHNL_VFR_VFACTIVE,
59693f1cac5SPaul Winder };
59793f1cac5SPaul Winder 
59893f1cac5SPaul Winder /**
59993f1cac5SPaul Winder  * virtchnl_vc_validate_vf_msg
60093f1cac5SPaul Winder  * @ver: Virtchnl version info
60193f1cac5SPaul Winder  * @v_opcode: Opcode for the message
60293f1cac5SPaul Winder  * @msg: pointer to the msg buffer
60393f1cac5SPaul Winder  * @msglen: msg length
60493f1cac5SPaul Winder  *
60593f1cac5SPaul Winder  * validate msg format against struct for each opcode
60693f1cac5SPaul Winder  */
60793f1cac5SPaul Winder static inline int
virtchnl_vc_validate_vf_msg(struct virtchnl_version_info * ver,u32 v_opcode,u8 * msg,u16 msglen)60893f1cac5SPaul Winder virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
60993f1cac5SPaul Winder 			    u8 *msg, u16 msglen)
61093f1cac5SPaul Winder {
61193f1cac5SPaul Winder 	bool err_msg_format = FALSE;
61293f1cac5SPaul Winder 	int valid_len = 0;
61393f1cac5SPaul Winder 
61493f1cac5SPaul Winder 	/* Validate message length. */
61593f1cac5SPaul Winder 	switch (v_opcode) {
61693f1cac5SPaul Winder 	case VIRTCHNL_OP_VERSION:
61793f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_version_info);
61893f1cac5SPaul Winder 		break;
61993f1cac5SPaul Winder 	case VIRTCHNL_OP_RESET_VF:
62093f1cac5SPaul Winder 		break;
62193f1cac5SPaul Winder 	case VIRTCHNL_OP_GET_VF_RESOURCES:
62293f1cac5SPaul Winder 		if (VF_IS_V11(ver))
62393f1cac5SPaul Winder 			valid_len = sizeof(u32);
62493f1cac5SPaul Winder 		break;
62593f1cac5SPaul Winder 	case VIRTCHNL_OP_CONFIG_TX_QUEUE:
62693f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_txq_info);
62793f1cac5SPaul Winder 		break;
62893f1cac5SPaul Winder 	case VIRTCHNL_OP_CONFIG_RX_QUEUE:
62993f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_rxq_info);
63093f1cac5SPaul Winder 		break;
63193f1cac5SPaul Winder 	case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
63293f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_vsi_queue_config_info);
63393f1cac5SPaul Winder 		if (msglen >= valid_len) {
63493f1cac5SPaul Winder 			struct virtchnl_vsi_queue_config_info *vqc =
63593f1cac5SPaul Winder 			    (struct virtchnl_vsi_queue_config_info *)msg;
63693f1cac5SPaul Winder 			valid_len += (vqc->num_queue_pairs *
63793f1cac5SPaul Winder 				      sizeof(struct
63893f1cac5SPaul Winder 					     virtchnl_queue_pair_info));
63993f1cac5SPaul Winder 			if (vqc->num_queue_pairs == 0)
64093f1cac5SPaul Winder 				err_msg_format = TRUE;
64193f1cac5SPaul Winder 		}
64293f1cac5SPaul Winder 		break;
64393f1cac5SPaul Winder 	case VIRTCHNL_OP_CONFIG_IRQ_MAP:
64493f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_irq_map_info);
64593f1cac5SPaul Winder 		if (msglen >= valid_len) {
64693f1cac5SPaul Winder 			struct virtchnl_irq_map_info *vimi =
64793f1cac5SPaul Winder 			    (struct virtchnl_irq_map_info *)msg;
64893f1cac5SPaul Winder 			valid_len += (vimi->num_vectors *
64993f1cac5SPaul Winder 				      sizeof(struct virtchnl_vector_map));
65093f1cac5SPaul Winder 			if (vimi->num_vectors == 0)
65193f1cac5SPaul Winder 				err_msg_format = TRUE;
65293f1cac5SPaul Winder 		}
65393f1cac5SPaul Winder 		break;
65493f1cac5SPaul Winder 	case VIRTCHNL_OP_ENABLE_QUEUES:
65593f1cac5SPaul Winder 	case VIRTCHNL_OP_DISABLE_QUEUES:
65693f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_queue_select);
65793f1cac5SPaul Winder 		break;
65893f1cac5SPaul Winder 	case VIRTCHNL_OP_ADD_ETH_ADDR:
65993f1cac5SPaul Winder 	case VIRTCHNL_OP_DEL_ETH_ADDR:
66093f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_ether_addr_list);
66193f1cac5SPaul Winder 		if (msglen >= valid_len) {
66293f1cac5SPaul Winder 			struct virtchnl_ether_addr_list *veal =
66393f1cac5SPaul Winder 			    (struct virtchnl_ether_addr_list *)msg;
66493f1cac5SPaul Winder 			valid_len += veal->num_elements *
66593f1cac5SPaul Winder 			    sizeof(struct virtchnl_ether_addr);
66693f1cac5SPaul Winder 			if (veal->num_elements == 0)
66793f1cac5SPaul Winder 				err_msg_format = TRUE;
66893f1cac5SPaul Winder 		}
66993f1cac5SPaul Winder 		break;
67093f1cac5SPaul Winder 	case VIRTCHNL_OP_ADD_VLAN:
67193f1cac5SPaul Winder 	case VIRTCHNL_OP_DEL_VLAN:
67293f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_vlan_filter_list);
67393f1cac5SPaul Winder 		if (msglen >= valid_len) {
67493f1cac5SPaul Winder 			struct virtchnl_vlan_filter_list *vfl =
67593f1cac5SPaul Winder 			    (struct virtchnl_vlan_filter_list *)msg;
67693f1cac5SPaul Winder 			valid_len += vfl->num_elements * sizeof(u16);
67793f1cac5SPaul Winder 			if (vfl->num_elements == 0)
67893f1cac5SPaul Winder 				err_msg_format = TRUE;
67993f1cac5SPaul Winder 		}
68093f1cac5SPaul Winder 		break;
68193f1cac5SPaul Winder 	case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
68293f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_promisc_info);
68393f1cac5SPaul Winder 		break;
68493f1cac5SPaul Winder 	case VIRTCHNL_OP_GET_STATS:
68593f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_queue_select);
68693f1cac5SPaul Winder 		break;
68793f1cac5SPaul Winder 	case VIRTCHNL_OP_IWARP:
68893f1cac5SPaul Winder 		/* These messages are opaque to us and will be validated in
68993f1cac5SPaul Winder 		 * the RDMA client code. We just need to check for nonzero
69093f1cac5SPaul Winder 		 * length. The firmware will enforce max length restrictions.
69193f1cac5SPaul Winder 		 */
69293f1cac5SPaul Winder 		if (msglen)
69393f1cac5SPaul Winder 			valid_len = msglen;
69493f1cac5SPaul Winder 		else
69593f1cac5SPaul Winder 			err_msg_format = TRUE;
69693f1cac5SPaul Winder 		break;
69793f1cac5SPaul Winder 	case VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP:
69893f1cac5SPaul Winder 		break;
69993f1cac5SPaul Winder 	case VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP:
70093f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_iwarp_qvlist_info);
70193f1cac5SPaul Winder 		if (msglen >= valid_len) {
70293f1cac5SPaul Winder 			struct virtchnl_iwarp_qvlist_info *qv =
70393f1cac5SPaul Winder 				(struct virtchnl_iwarp_qvlist_info *)msg;
70493f1cac5SPaul Winder 			if (qv->num_vectors == 0) {
70593f1cac5SPaul Winder 				err_msg_format = TRUE;
70693f1cac5SPaul Winder 				break;
70793f1cac5SPaul Winder 			}
70893f1cac5SPaul Winder 			valid_len += ((qv->num_vectors - 1) *
70993f1cac5SPaul Winder 				sizeof(struct virtchnl_iwarp_qv_info));
71093f1cac5SPaul Winder 		}
71193f1cac5SPaul Winder 		break;
71293f1cac5SPaul Winder 	case VIRTCHNL_OP_CONFIG_RSS_KEY:
71393f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_rss_key);
71493f1cac5SPaul Winder 		if (msglen >= valid_len) {
71593f1cac5SPaul Winder 			struct virtchnl_rss_key *vrk =
71693f1cac5SPaul Winder 				(struct virtchnl_rss_key *)msg;
71793f1cac5SPaul Winder 			valid_len += vrk->key_len - 1;
71893f1cac5SPaul Winder 		}
71993f1cac5SPaul Winder 		break;
72093f1cac5SPaul Winder 	case VIRTCHNL_OP_CONFIG_RSS_LUT:
72193f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_rss_lut);
72293f1cac5SPaul Winder 		if (msglen >= valid_len) {
72393f1cac5SPaul Winder 			struct virtchnl_rss_lut *vrl =
72493f1cac5SPaul Winder 				(struct virtchnl_rss_lut *)msg;
72593f1cac5SPaul Winder 			valid_len += vrl->lut_entries - 1;
72693f1cac5SPaul Winder 		}
72793f1cac5SPaul Winder 		break;
72893f1cac5SPaul Winder 	case VIRTCHNL_OP_GET_RSS_HENA_CAPS:
72993f1cac5SPaul Winder 		break;
73093f1cac5SPaul Winder 	case VIRTCHNL_OP_SET_RSS_HENA:
73193f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_rss_hena);
73293f1cac5SPaul Winder 		break;
73393f1cac5SPaul Winder 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
73493f1cac5SPaul Winder 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
73593f1cac5SPaul Winder 		break;
73693f1cac5SPaul Winder 	case VIRTCHNL_OP_REQUEST_QUEUES:
73793f1cac5SPaul Winder 		valid_len = sizeof(struct virtchnl_vf_res_request);
73893f1cac5SPaul Winder 		break;
73993f1cac5SPaul Winder 	/* These are always errors coming from the VF. */
74093f1cac5SPaul Winder 	case VIRTCHNL_OP_EVENT:
74193f1cac5SPaul Winder 	case VIRTCHNL_OP_UNKNOWN:
74293f1cac5SPaul Winder 	default:
74393f1cac5SPaul Winder 		return VIRTCHNL_ERR_PARAM;
74493f1cac5SPaul Winder 	}
74593f1cac5SPaul Winder 	/* few more checks */
74693f1cac5SPaul Winder 	if (err_msg_format || valid_len != msglen)
74793f1cac5SPaul Winder 		return VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH;
74893f1cac5SPaul Winder 
74993f1cac5SPaul Winder 	return 0;
75093f1cac5SPaul Winder }
75193f1cac5SPaul Winder #endif /* _VIRTCHNL_H_ */
752