1333149Serj/******************************************************************************
2333149Serj
3349163Serj  Copyright (c) 2013-2019, Intel Corporation
4333149Serj  All rights reserved.
5333149Serj
6333149Serj  Redistribution and use in source and binary forms, with or without
7333149Serj  modification, are permitted provided that the following conditions are met:
8333149Serj
9333149Serj   1. Redistributions of source code must retain the above copyright notice,
10333149Serj      this list of conditions and the following disclaimer.
11333149Serj
12333149Serj   2. Redistributions in binary form must reproduce the above copyright
13333149Serj      notice, this list of conditions and the following disclaimer in the
14333149Serj      documentation and/or other materials provided with the distribution.
15333149Serj
16333149Serj   3. Neither the name of the Intel Corporation nor the names of its
17333149Serj      contributors may be used to endorse or promote products derived from
18333149Serj      this software without specific prior written permission.
19333149Serj
20333149Serj  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21333149Serj  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22333149Serj  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23333149Serj  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24333149Serj  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25333149Serj  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26333149Serj  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27333149Serj  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28333149Serj  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29333149Serj  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30333149Serj  POSSIBILITY OF SUCH DAMAGE.
31333149Serj
32333149Serj******************************************************************************/
33333149Serj/*$FreeBSD: stable/11/sys/dev/ixl/virtchnl.h 349163 2019-06-18 00:08:02Z erj $*/
34333149Serj
35349163Serj
36333149Serj#ifndef _VIRTCHNL_H_
37333149Serj#define _VIRTCHNL_H_
38333149Serj
39333149Serj/* Description:
40333149Serj * This header file describes the VF-PF communication protocol used
41333149Serj * by the drivers for all devices starting from our 40G product line
42333149Serj *
43333149Serj * Admin queue buffer usage:
44333149Serj * desc->opcode is always aqc_opc_send_msg_to_pf
45333149Serj * flags, retval, datalen, and data addr are all used normally.
46333149Serj * The Firmware copies the cookie fields when sending messages between the
47333149Serj * PF and VF, but uses all other fields internally. Due to this limitation,
48333149Serj * we must send all messages as "indirect", i.e. using an external buffer.
49333149Serj *
50333149Serj * All the VSI indexes are relative to the VF. Each VF can have maximum of
51333149Serj * three VSIs. All the queue indexes are relative to the VSI.  Each VF can
52333149Serj * have a maximum of sixteen queues for all of its VSIs.
53333149Serj *
54333149Serj * The PF is required to return a status code in v_retval for all messages
55333149Serj * except RESET_VF, which does not require any response. The return value
56333149Serj * is of status_code type, defined in the shared type.h.
57333149Serj *
58333149Serj * In general, VF driver initialization should roughly follow the order of
59333149Serj * these opcodes. The VF driver must first validate the API version of the
60333149Serj * PF driver, then request a reset, then get resources, then configure
61333149Serj * queues and interrupts. After these operations are complete, the VF
62333149Serj * driver may start its queues, optionally add MAC and VLAN filters, and
63333149Serj * process traffic.
64333149Serj */
65333149Serj
66333149Serj/* START GENERIC DEFINES
67333149Serj * Need to ensure the following enums and defines hold the same meaning and
68333149Serj * value in current and future projects
69333149Serj */
70333149Serj
71333149Serj/* Error Codes */
72333149Serjenum virtchnl_status_code {
73333149Serj	VIRTCHNL_STATUS_SUCCESS				= 0,
74349163Serj	VIRTCHNL_STATUS_ERR_PARAM			= -5,
75349163Serj	VIRTCHNL_STATUS_ERR_NO_MEMORY			= -18,
76333149Serj	VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH		= -38,
77333149Serj	VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR		= -39,
78333149Serj	VIRTCHNL_STATUS_ERR_INVALID_VF_ID		= -40,
79349163Serj	VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR		= -53,
80349163Serj	VIRTCHNL_STATUS_ERR_NOT_SUPPORTED		= -64,
81333149Serj};
82333149Serj
83349163Serj/* Backward compatibility */
84349163Serj#define VIRTCHNL_ERR_PARAM VIRTCHNL_STATUS_ERR_PARAM
85349163Serj#define VIRTCHNL_STATUS_NOT_SUPPORTED VIRTCHNL_STATUS_ERR_NOT_SUPPORTED
86349163Serj
87349163Serj#define VIRTCHNL_LINK_SPEED_2_5GB_SHIFT		0x0
88333149Serj#define VIRTCHNL_LINK_SPEED_100MB_SHIFT		0x1
89333149Serj#define VIRTCHNL_LINK_SPEED_1000MB_SHIFT	0x2
90333149Serj#define VIRTCHNL_LINK_SPEED_10GB_SHIFT		0x3
91333149Serj#define VIRTCHNL_LINK_SPEED_40GB_SHIFT		0x4
92333149Serj#define VIRTCHNL_LINK_SPEED_20GB_SHIFT		0x5
93333149Serj#define VIRTCHNL_LINK_SPEED_25GB_SHIFT		0x6
94349163Serj#define VIRTCHNL_LINK_SPEED_5GB_SHIFT		0x7
95333149Serj
96333149Serjenum virtchnl_link_speed {
97333149Serj	VIRTCHNL_LINK_SPEED_UNKNOWN	= 0,
98333149Serj	VIRTCHNL_LINK_SPEED_100MB	= BIT(VIRTCHNL_LINK_SPEED_100MB_SHIFT),
99333149Serj	VIRTCHNL_LINK_SPEED_1GB		= BIT(VIRTCHNL_LINK_SPEED_1000MB_SHIFT),
100333149Serj	VIRTCHNL_LINK_SPEED_10GB	= BIT(VIRTCHNL_LINK_SPEED_10GB_SHIFT),
101333149Serj	VIRTCHNL_LINK_SPEED_40GB	= BIT(VIRTCHNL_LINK_SPEED_40GB_SHIFT),
102333149Serj	VIRTCHNL_LINK_SPEED_20GB	= BIT(VIRTCHNL_LINK_SPEED_20GB_SHIFT),
103333149Serj	VIRTCHNL_LINK_SPEED_25GB	= BIT(VIRTCHNL_LINK_SPEED_25GB_SHIFT),
104349163Serj	VIRTCHNL_LINK_SPEED_2_5GB	= BIT(VIRTCHNL_LINK_SPEED_2_5GB_SHIFT),
105349163Serj	VIRTCHNL_LINK_SPEED_5GB		= BIT(VIRTCHNL_LINK_SPEED_5GB_SHIFT),
106333149Serj};
107333149Serj
108333149Serj/* for hsplit_0 field of Rx HMC context */
109333149Serj/* deprecated with AVF 1.0 */
110333149Serjenum virtchnl_rx_hsplit {
111333149Serj	VIRTCHNL_RX_HSPLIT_NO_SPLIT      = 0,
112333149Serj	VIRTCHNL_RX_HSPLIT_SPLIT_L2      = 1,
113333149Serj	VIRTCHNL_RX_HSPLIT_SPLIT_IP      = 2,
114333149Serj	VIRTCHNL_RX_HSPLIT_SPLIT_TCP_UDP = 4,
115333149Serj	VIRTCHNL_RX_HSPLIT_SPLIT_SCTP    = 8,
116333149Serj};
117333149Serj
118333149Serj#define VIRTCHNL_ETH_LENGTH_OF_ADDRESS	6
119333149Serj/* END GENERIC DEFINES */
120333149Serj
121333149Serj/* Opcodes for VF-PF communication. These are placed in the v_opcode field
122333149Serj * of the virtchnl_msg structure.
123333149Serj */
124333149Serjenum virtchnl_ops {
125333149Serj/* The PF sends status change events to VFs using
126333149Serj * the VIRTCHNL_OP_EVENT opcode.
127333149Serj * VFs send requests to the PF using the other ops.
128333149Serj * Use of "advanced opcode" features must be negotiated as part of capabilities
129333149Serj * exchange and are not considered part of base mode feature set.
130333149Serj */
131333149Serj	VIRTCHNL_OP_UNKNOWN = 0,
132333149Serj	VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */
133333149Serj	VIRTCHNL_OP_RESET_VF = 2,
134333149Serj	VIRTCHNL_OP_GET_VF_RESOURCES = 3,
135333149Serj	VIRTCHNL_OP_CONFIG_TX_QUEUE = 4,
136333149Serj	VIRTCHNL_OP_CONFIG_RX_QUEUE = 5,
137333149Serj	VIRTCHNL_OP_CONFIG_VSI_QUEUES = 6,
138333149Serj	VIRTCHNL_OP_CONFIG_IRQ_MAP = 7,
139333149Serj	VIRTCHNL_OP_ENABLE_QUEUES = 8,
140333149Serj	VIRTCHNL_OP_DISABLE_QUEUES = 9,
141333149Serj	VIRTCHNL_OP_ADD_ETH_ADDR = 10,
142333149Serj	VIRTCHNL_OP_DEL_ETH_ADDR = 11,
143333149Serj	VIRTCHNL_OP_ADD_VLAN = 12,
144333149Serj	VIRTCHNL_OP_DEL_VLAN = 13,
145333149Serj	VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14,
146333149Serj	VIRTCHNL_OP_GET_STATS = 15,
147333149Serj	VIRTCHNL_OP_RSVD = 16,
148333149Serj	VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */
149349163Serj	/* opcode 19 is reserved */
150333149Serj	VIRTCHNL_OP_IWARP = 20, /* advanced opcode */
151333149Serj	VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21, /* advanced opcode */
152333149Serj	VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP = 22, /* advanced opcode */
153333149Serj	VIRTCHNL_OP_CONFIG_RSS_KEY = 23,
154333149Serj	VIRTCHNL_OP_CONFIG_RSS_LUT = 24,
155333149Serj	VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25,
156333149Serj	VIRTCHNL_OP_SET_RSS_HENA = 26,
157333149Serj	VIRTCHNL_OP_ENABLE_VLAN_STRIPPING = 27,
158333149Serj	VIRTCHNL_OP_DISABLE_VLAN_STRIPPING = 28,
159333149Serj	VIRTCHNL_OP_REQUEST_QUEUES = 29,
160349163Serj	VIRTCHNL_OP_ENABLE_CHANNELS = 30,
161349163Serj	VIRTCHNL_OP_DISABLE_CHANNELS = 31,
162349163Serj	VIRTCHNL_OP_ADD_CLOUD_FILTER = 32,
163349163Serj	VIRTCHNL_OP_DEL_CLOUD_FILTER = 33,
164333149Serj};
165333149Serj
166349163Serj/* These macros are used to generate compilation errors if a structure/union
167333149Serj * is not exactly the correct length. It gives a divide by zero error if the
168349163Serj * structure/union is not of the correct size, otherwise it creates an enum
169349163Serj * that is never used.
170333149Serj */
171333149Serj#define VIRTCHNL_CHECK_STRUCT_LEN(n, X) enum virtchnl_static_assert_enum_##X \
172349163Serj	{ virtchnl_static_assert_##X = (n)/((sizeof(struct X) == (n)) ? 1 : 0) }
173349163Serj#define VIRTCHNL_CHECK_UNION_LEN(n, X) enum virtchnl_static_asset_enum_##X \
174349163Serj	{ virtchnl_static_assert_##X = (n)/((sizeof(union X) == (n)) ? 1 : 0) }
175333149Serj
176333149Serj/* Virtual channel message descriptor. This overlays the admin queue
177333149Serj * descriptor. All other data is passed in external buffers.
178333149Serj */
179333149Serj
180333149Serjstruct virtchnl_msg {
181333149Serj	u8 pad[8];			 /* AQ flags/opcode/len/retval fields */
182333149Serj	enum virtchnl_ops v_opcode; /* avoid confusion with desc->opcode */
183333149Serj	enum virtchnl_status_code v_retval;  /* ditto for desc->retval */
184333149Serj	u32 vfid;			 /* used by PF when sending to VF */
185333149Serj};
186333149Serj
187333149SerjVIRTCHNL_CHECK_STRUCT_LEN(20, virtchnl_msg);
188333149Serj
189349163Serj/* Message descriptions and data structures. */
190333149Serj
191333149Serj/* VIRTCHNL_OP_VERSION
192333149Serj * VF posts its version number to the PF. PF responds with its version number
193333149Serj * in the same format, along with a return code.
194333149Serj * Reply from PF has its major/minor versions also in param0 and param1.
195333149Serj * If there is a major version mismatch, then the VF cannot operate.
196333149Serj * If there is a minor version mismatch, then the VF can operate but should
197333149Serj * add a warning to the system log.
198333149Serj *
199333149Serj * This enum element MUST always be specified as == 1, regardless of other
200333149Serj * changes in the API. The PF must always respond to this message without
201333149Serj * error regardless of version mismatch.
202333149Serj */
203333149Serj#define VIRTCHNL_VERSION_MAJOR		1
204333149Serj#define VIRTCHNL_VERSION_MINOR		1
205333149Serj#define VIRTCHNL_VERSION_MINOR_NO_VF_CAPS	0
206333149Serj
207333149Serjstruct virtchnl_version_info {
208333149Serj	u32 major;
209333149Serj	u32 minor;
210333149Serj};
211333149Serj
212333149SerjVIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_version_info);
213333149Serj
214333149Serj#define VF_IS_V10(_v) (((_v)->major == 1) && ((_v)->minor == 0))
215333149Serj#define VF_IS_V11(_ver) (((_ver)->major == 1) && ((_ver)->minor == 1))
216333149Serj
217333149Serj/* VIRTCHNL_OP_RESET_VF
218333149Serj * VF sends this request to PF with no parameters
219333149Serj * PF does NOT respond! VF driver must delay then poll VFGEN_RSTAT register
220333149Serj * until reset completion is indicated. The admin queue must be reinitialized
221333149Serj * after this operation.
222333149Serj *
223333149Serj * When reset is complete, PF must ensure that all queues in all VSIs associated
224333149Serj * with the VF are stopped, all queue configurations in the HMC are set to 0,
225333149Serj * and all MAC and VLAN filters (except the default MAC address) on all VSIs
226333149Serj * are cleared.
227333149Serj */
228333149Serj
229333149Serj/* VSI types that use VIRTCHNL interface for VF-PF communication. VSI_SRIOV
230333149Serj * vsi_type should always be 6 for backward compatibility. Add other fields
231333149Serj * as needed.
232333149Serj */
233333149Serjenum virtchnl_vsi_type {
234333149Serj	VIRTCHNL_VSI_TYPE_INVALID = 0,
235333149Serj	VIRTCHNL_VSI_SRIOV = 6,
236333149Serj};
237333149Serj
238333149Serj/* VIRTCHNL_OP_GET_VF_RESOURCES
239333149Serj * Version 1.0 VF sends this request to PF with no parameters
240333149Serj * Version 1.1 VF sends this request to PF with u32 bitmap of its capabilities
241333149Serj * PF responds with an indirect message containing
242333149Serj * virtchnl_vf_resource and one or more
243333149Serj * virtchnl_vsi_resource structures.
244333149Serj */
245333149Serj
246333149Serjstruct virtchnl_vsi_resource {
247333149Serj	u16 vsi_id;
248333149Serj	u16 num_queue_pairs;
249333149Serj	enum virtchnl_vsi_type vsi_type;
250333149Serj	u16 qset_handle;
251333149Serj	u8 default_mac_addr[VIRTCHNL_ETH_LENGTH_OF_ADDRESS];
252333149Serj};
253333149Serj
254333149SerjVIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource);
255333149Serj
256333149Serj/* VF capability flags
257333149Serj * VIRTCHNL_VF_OFFLOAD_L2 flag is inclusive of base mode L2 offloads including
258333149Serj * TX/RX Checksum offloading and TSO for non-tunnelled packets.
259333149Serj */
260333149Serj#define VIRTCHNL_VF_OFFLOAD_L2			0x00000001
261333149Serj#define VIRTCHNL_VF_OFFLOAD_IWARP		0x00000002
262333149Serj#define VIRTCHNL_VF_OFFLOAD_RSVD		0x00000004
263333149Serj#define VIRTCHNL_VF_OFFLOAD_RSS_AQ		0x00000008
264333149Serj#define VIRTCHNL_VF_OFFLOAD_RSS_REG		0x00000010
265333149Serj#define VIRTCHNL_VF_OFFLOAD_WB_ON_ITR		0x00000020
266333149Serj#define VIRTCHNL_VF_OFFLOAD_REQ_QUEUES		0x00000040
267349163Serj#define VIRTCHNL_VF_OFFLOAD_CRC			0x00000080
268333149Serj#define VIRTCHNL_VF_OFFLOAD_VLAN		0x00010000
269333149Serj#define VIRTCHNL_VF_OFFLOAD_RX_POLLING		0x00020000
270333149Serj#define VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2	0x00040000
271333149Serj#define VIRTCHNL_VF_OFFLOAD_RSS_PF		0X00080000
272333149Serj#define VIRTCHNL_VF_OFFLOAD_ENCAP		0X00100000
273333149Serj#define VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM		0X00200000
274333149Serj#define VIRTCHNL_VF_OFFLOAD_RX_ENCAP_CSUM	0X00400000
275349163Serj#define VIRTCHNL_VF_OFFLOAD_ADQ			0X00800000
276349163Serj/* Define below the capability flags that are not offloads */
277349163Serj#define VIRTCHNL_VF_CAP_ADV_LINK_SPEED		0x00000080
278333149Serj#define VF_BASE_MODE_OFFLOADS (VIRTCHNL_VF_OFFLOAD_L2 | \
279333149Serj			       VIRTCHNL_VF_OFFLOAD_VLAN | \
280333149Serj			       VIRTCHNL_VF_OFFLOAD_RSS_PF)
281333149Serj
282333149Serjstruct virtchnl_vf_resource {
283333149Serj	u16 num_vsis;
284333149Serj	u16 num_queue_pairs;
285333149Serj	u16 max_vectors;
286333149Serj	u16 max_mtu;
287333149Serj
288333149Serj	u32 vf_cap_flags;
289333149Serj	u32 rss_key_size;
290333149Serj	u32 rss_lut_size;
291333149Serj
292333149Serj	struct virtchnl_vsi_resource vsi_res[1];
293333149Serj};
294333149Serj
295333149SerjVIRTCHNL_CHECK_STRUCT_LEN(36, virtchnl_vf_resource);
296333149Serj
297333149Serj/* VIRTCHNL_OP_CONFIG_TX_QUEUE
298333149Serj * VF sends this message to set up parameters for one TX queue.
299333149Serj * External data buffer contains one instance of virtchnl_txq_info.
300333149Serj * PF configures requested queue and returns a status code.
301333149Serj */
302333149Serj
303333149Serj/* Tx queue config info */
304333149Serjstruct virtchnl_txq_info {
305333149Serj	u16 vsi_id;
306333149Serj	u16 queue_id;
307333149Serj	u16 ring_len;		/* number of descriptors, multiple of 8 */
308333149Serj	u16 headwb_enabled; /* deprecated with AVF 1.0 */
309333149Serj	u64 dma_ring_addr;
310333149Serj	u64 dma_headwb_addr; /* deprecated with AVF 1.0 */
311333149Serj};
312333149Serj
313333149SerjVIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_txq_info);
314333149Serj
315333149Serj/* VIRTCHNL_OP_CONFIG_RX_QUEUE
316333149Serj * VF sends this message to set up parameters for one RX queue.
317333149Serj * External data buffer contains one instance of virtchnl_rxq_info.
318349163Serj * PF configures requested queue and returns a status code. The
319349163Serj * crc_disable flag disables CRC stripping on the VF. Setting
320349163Serj * the crc_disable flag to 1 will disable CRC stripping for each
321349163Serj * queue in the VF where the flag is set. The VIRTCHNL_VF_OFFLOAD_CRC
322349163Serj * offload must have been set prior to sending this info or the PF
323349163Serj * will ignore the request. This flag should be set the same for
324349163Serj * all of the queues for a VF.
325333149Serj */
326333149Serj
327333149Serj/* Rx queue config info */
328333149Serjstruct virtchnl_rxq_info {
329333149Serj	u16 vsi_id;
330333149Serj	u16 queue_id;
331333149Serj	u32 ring_len;		/* number of descriptors, multiple of 32 */
332333149Serj	u16 hdr_size;
333333149Serj	u16 splithdr_enabled; /* deprecated with AVF 1.0 */
334333149Serj	u32 databuffer_size;
335333149Serj	u32 max_pkt_size;
336349163Serj	u8 crc_disable;
337349163Serj	u8 pad1[3];
338333149Serj	u64 dma_ring_addr;
339333149Serj	enum virtchnl_rx_hsplit rx_split_pos; /* deprecated with AVF 1.0 */
340333149Serj	u32 pad2;
341333149Serj};
342333149Serj
343333149SerjVIRTCHNL_CHECK_STRUCT_LEN(40, virtchnl_rxq_info);
344333149Serj
345333149Serj/* VIRTCHNL_OP_CONFIG_VSI_QUEUES
346349163Serj * VF sends this message to set parameters for active TX and RX queues
347333149Serj * associated with the specified VSI.
348333149Serj * PF configures queues and returns status.
349333149Serj * If the number of queues specified is greater than the number of queues
350333149Serj * associated with the VSI, an error is returned and no queues are configured.
351349163Serj * NOTE: The VF is not required to configure all queues in a single request.
352349163Serj * It may send multiple messages. PF drivers must correctly handle all VF
353349163Serj * requests.
354333149Serj */
355333149Serjstruct virtchnl_queue_pair_info {
356333149Serj	/* NOTE: vsi_id and queue_id should be identical for both queues. */
357333149Serj	struct virtchnl_txq_info txq;
358333149Serj	struct virtchnl_rxq_info rxq;
359333149Serj};
360333149Serj
361333149SerjVIRTCHNL_CHECK_STRUCT_LEN(64, virtchnl_queue_pair_info);
362333149Serj
363333149Serjstruct virtchnl_vsi_queue_config_info {
364333149Serj	u16 vsi_id;
365333149Serj	u16 num_queue_pairs;
366333149Serj	u32 pad;
367333149Serj	struct virtchnl_queue_pair_info qpair[1];
368333149Serj};
369333149Serj
370333149SerjVIRTCHNL_CHECK_STRUCT_LEN(72, virtchnl_vsi_queue_config_info);
371333149Serj
372333149Serj/* VIRTCHNL_OP_REQUEST_QUEUES
373333149Serj * VF sends this message to request the PF to allocate additional queues to
374333149Serj * this VF.  Each VF gets a guaranteed number of queues on init but asking for
375333149Serj * additional queues must be negotiated.  This is a best effort request as it
376333149Serj * is possible the PF does not have enough queues left to support the request.
377333149Serj * If the PF cannot support the number requested it will respond with the
378333149Serj * maximum number it is able to support; otherwise it will respond with the
379333149Serj * number requested.
380333149Serj */
381333149Serj
382333149Serj/* VF resource request */
383333149Serjstruct virtchnl_vf_res_request {
384333149Serj	u16 num_queue_pairs;
385333149Serj};
386333149Serj
387333149Serj/* VIRTCHNL_OP_CONFIG_IRQ_MAP
388333149Serj * VF uses this message to map vectors to queues.
389333149Serj * The rxq_map and txq_map fields are bitmaps used to indicate which queues
390333149Serj * are to be associated with the specified vector.
391349163Serj * The "other" causes are always mapped to vector 0. The VF may not request
392349163Serj * that vector 0 be used for traffic.
393333149Serj * PF configures interrupt mapping and returns status.
394349163Serj * NOTE: due to hardware requirements, all active queues (both TX and RX)
395349163Serj * should be mapped to interrupts, even if the driver intends to operate
396349163Serj * only in polling mode. In this case the interrupt may be disabled, but
397349163Serj * the ITR timer will still run to trigger writebacks.
398333149Serj */
399333149Serjstruct virtchnl_vector_map {
400333149Serj	u16 vsi_id;
401333149Serj	u16 vector_id;
402333149Serj	u16 rxq_map;
403333149Serj	u16 txq_map;
404333149Serj	u16 rxitr_idx;
405333149Serj	u16 txitr_idx;
406333149Serj};
407333149Serj
408333149SerjVIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_vector_map);
409333149Serj
410333149Serjstruct virtchnl_irq_map_info {
411333149Serj	u16 num_vectors;
412333149Serj	struct virtchnl_vector_map vecmap[1];
413333149Serj};
414333149Serj
415333149SerjVIRTCHNL_CHECK_STRUCT_LEN(14, virtchnl_irq_map_info);
416333149Serj
417333149Serj/* VIRTCHNL_OP_ENABLE_QUEUES
418333149Serj * VIRTCHNL_OP_DISABLE_QUEUES
419333149Serj * VF sends these message to enable or disable TX/RX queue pairs.
420333149Serj * The queues fields are bitmaps indicating which queues to act upon.
421333149Serj * (Currently, we only support 16 queues per VF, but we make the field
422333149Serj * u32 to allow for expansion.)
423333149Serj * PF performs requested action and returns status.
424349163Serj * NOTE: The VF is not required to enable/disable all queues in a single
425349163Serj * request. It may send multiple messages.
426349163Serj * PF drivers must correctly handle all VF requests.
427333149Serj */
428333149Serjstruct virtchnl_queue_select {
429333149Serj	u16 vsi_id;
430333149Serj	u16 pad;
431333149Serj	u32 rx_queues;
432333149Serj	u32 tx_queues;
433333149Serj};
434333149Serj
435333149SerjVIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_queue_select);
436333149Serj
437333149Serj/* VIRTCHNL_OP_ADD_ETH_ADDR
438333149Serj * VF sends this message in order to add one or more unicast or multicast
439333149Serj * address filters for the specified VSI.
440333149Serj * PF adds the filters and returns status.
441333149Serj */
442333149Serj
443333149Serj/* VIRTCHNL_OP_DEL_ETH_ADDR
444333149Serj * VF sends this message in order to remove one or more unicast or multicast
445333149Serj * filters for the specified VSI.
446333149Serj * PF removes the filters and returns status.
447333149Serj */
448333149Serj
449333149Serjstruct virtchnl_ether_addr {
450333149Serj	u8 addr[VIRTCHNL_ETH_LENGTH_OF_ADDRESS];
451333149Serj	u8 pad[2];
452333149Serj};
453333149Serj
454333149SerjVIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_ether_addr);
455333149Serj
456333149Serjstruct virtchnl_ether_addr_list {
457333149Serj	u16 vsi_id;
458333149Serj	u16 num_elements;
459333149Serj	struct virtchnl_ether_addr list[1];
460333149Serj};
461333149Serj
462333149SerjVIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_ether_addr_list);
463333149Serj
464333149Serj/* VIRTCHNL_OP_ADD_VLAN
465333149Serj * VF sends this message to add one or more VLAN tag filters for receives.
466333149Serj * PF adds the filters and returns status.
467333149Serj * If a port VLAN is configured by the PF, this operation will return an
468333149Serj * error to the VF.
469333149Serj */
470333149Serj
471333149Serj/* VIRTCHNL_OP_DEL_VLAN
472333149Serj * VF sends this message to remove one or more VLAN tag filters for receives.
473333149Serj * PF removes the filters and returns status.
474333149Serj * If a port VLAN is configured by the PF, this operation will return an
475333149Serj * error to the VF.
476333149Serj */
477333149Serj
478333149Serjstruct virtchnl_vlan_filter_list {
479333149Serj	u16 vsi_id;
480333149Serj	u16 num_elements;
481333149Serj	u16 vlan_id[1];
482333149Serj};
483333149Serj
484333149SerjVIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_vlan_filter_list);
485333149Serj
486333149Serj/* VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE
487333149Serj * VF sends VSI id and flags.
488333149Serj * PF returns status code in retval.
489333149Serj * Note: we assume that broadcast accept mode is always enabled.
490333149Serj */
491333149Serjstruct virtchnl_promisc_info {
492333149Serj	u16 vsi_id;
493333149Serj	u16 flags;
494333149Serj};
495333149Serj
496333149SerjVIRTCHNL_CHECK_STRUCT_LEN(4, virtchnl_promisc_info);
497333149Serj
498333149Serj#define FLAG_VF_UNICAST_PROMISC	0x00000001
499333149Serj#define FLAG_VF_MULTICAST_PROMISC	0x00000002
500333149Serj
501333149Serj/* VIRTCHNL_OP_GET_STATS
502333149Serj * VF sends this message to request stats for the selected VSI. VF uses
503333149Serj * the virtchnl_queue_select struct to specify the VSI. The queue_id
504333149Serj * field is ignored by the PF.
505333149Serj *
506349163Serj * PF replies with struct virtchnl_eth_stats in an external buffer.
507333149Serj */
508333149Serj
509349163Serjstruct virtchnl_eth_stats {
510349163Serj	u64 rx_bytes;			/* received bytes */
511349163Serj	u64 rx_unicast;			/* received unicast pkts */
512349163Serj	u64 rx_multicast;		/* received multicast pkts */
513349163Serj	u64 rx_broadcast;		/* received broadcast pkts */
514349163Serj	u64 rx_discards;
515349163Serj	u64 rx_unknown_protocol;
516349163Serj	u64 tx_bytes;			/* transmitted bytes */
517349163Serj	u64 tx_unicast;			/* transmitted unicast pkts */
518349163Serj	u64 tx_multicast;		/* transmitted multicast pkts */
519349163Serj	u64 tx_broadcast;		/* transmitted broadcast pkts */
520349163Serj	u64 tx_discards;
521349163Serj	u64 tx_errors;
522349163Serj};
523349163Serj
524333149Serj/* VIRTCHNL_OP_CONFIG_RSS_KEY
525333149Serj * VIRTCHNL_OP_CONFIG_RSS_LUT
526333149Serj * VF sends these messages to configure RSS. Only supported if both PF
527333149Serj * and VF drivers set the VIRTCHNL_VF_OFFLOAD_RSS_PF bit during
528333149Serj * configuration negotiation. If this is the case, then the RSS fields in
529333149Serj * the VF resource struct are valid.
530333149Serj * Both the key and LUT are initialized to 0 by the PF, meaning that
531333149Serj * RSS is effectively disabled until set up by the VF.
532333149Serj */
533333149Serjstruct virtchnl_rss_key {
534333149Serj	u16 vsi_id;
535333149Serj	u16 key_len;
536333149Serj	u8 key[1];         /* RSS hash key, packed bytes */
537333149Serj};
538333149Serj
539333149SerjVIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_key);
540333149Serj
541333149Serjstruct virtchnl_rss_lut {
542333149Serj	u16 vsi_id;
543333149Serj	u16 lut_entries;
544333149Serj	u8 lut[1];        /* RSS lookup table */
545333149Serj};
546333149Serj
547333149SerjVIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_lut);
548333149Serj
549333149Serj/* VIRTCHNL_OP_GET_RSS_HENA_CAPS
550333149Serj * VIRTCHNL_OP_SET_RSS_HENA
551333149Serj * VF sends these messages to get and set the hash filter enable bits for RSS.
552333149Serj * By default, the PF sets these to all possible traffic types that the
553333149Serj * hardware supports. The VF can query this value if it wants to change the
554333149Serj * traffic types that are hashed by the hardware.
555333149Serj */
556333149Serjstruct virtchnl_rss_hena {
557333149Serj	u64 hena;
558333149Serj};
559333149Serj
560333149SerjVIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_rss_hena);
561333149Serj
562349163Serj/* VIRTCHNL_OP_ENABLE_CHANNELS
563349163Serj * VIRTCHNL_OP_DISABLE_CHANNELS
564349163Serj * VF sends these messages to enable or disable channels based on
565349163Serj * the user specified queue count and queue offset for each traffic class.
566349163Serj * This struct encompasses all the information that the PF needs from
567349163Serj * VF to create a channel.
568349163Serj */
569349163Serjstruct virtchnl_channel_info {
570349163Serj	u16 count; /* number of queues in a channel */
571349163Serj	u16 offset; /* queues in a channel start from 'offset' */
572349163Serj	u32 pad;
573349163Serj	u64 max_tx_rate;
574349163Serj};
575349163Serj
576349163SerjVIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_channel_info);
577349163Serj
578349163Serjstruct virtchnl_tc_info {
579349163Serj	u32	num_tc;
580349163Serj	u32	pad;
581349163Serj	struct	virtchnl_channel_info list[1];
582349163Serj};
583349163Serj
584349163SerjVIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_tc_info);
585349163Serj
586349163Serj/* VIRTCHNL_ADD_CLOUD_FILTER
587349163Serj * VIRTCHNL_DEL_CLOUD_FILTER
588349163Serj * VF sends these messages to add or delete a cloud filter based on the
589349163Serj * user specified match and action filters. These structures encompass
590349163Serj * all the information that the PF needs from the VF to add/delete a
591349163Serj * cloud filter.
592349163Serj */
593349163Serj
594349163Serjstruct virtchnl_l4_spec {
595349163Serj	u8	src_mac[ETH_ALEN];
596349163Serj	u8	dst_mac[ETH_ALEN];
597349163Serj	__be16	vlan_id;
598349163Serj	__be16	pad; /* reserved for future use */
599349163Serj	__be32	src_ip[4];
600349163Serj	__be32	dst_ip[4];
601349163Serj	__be16	src_port;
602349163Serj	__be16	dst_port;
603349163Serj};
604349163Serj
605349163SerjVIRTCHNL_CHECK_STRUCT_LEN(52, virtchnl_l4_spec);
606349163Serj
607349163Serjunion virtchnl_flow_spec {
608349163Serj	struct	virtchnl_l4_spec tcp_spec;
609349163Serj	u8	buffer[128]; /* reserved for future use */
610349163Serj};
611349163Serj
612349163SerjVIRTCHNL_CHECK_UNION_LEN(128, virtchnl_flow_spec);
613349163Serj
614349163Serjenum virtchnl_action {
615349163Serj	/* action types */
616349163Serj	VIRTCHNL_ACTION_DROP = 0,
617349163Serj	VIRTCHNL_ACTION_TC_REDIRECT,
618349163Serj};
619349163Serj
620349163Serjenum virtchnl_flow_type {
621349163Serj	/* flow types */
622349163Serj	VIRTCHNL_TCP_V4_FLOW = 0,
623349163Serj	VIRTCHNL_TCP_V6_FLOW,
624349163Serj};
625349163Serj
626349163Serjstruct virtchnl_filter {
627349163Serj	union	virtchnl_flow_spec data;
628349163Serj	union	virtchnl_flow_spec mask;
629349163Serj	enum	virtchnl_flow_type flow_type;
630349163Serj	enum	virtchnl_action action;
631349163Serj	u32	action_meta;
632349163Serj	u8	field_flags;
633349163Serj};
634349163Serj
635349163SerjVIRTCHNL_CHECK_STRUCT_LEN(272, virtchnl_filter);
636349163Serj
637333149Serj/* VIRTCHNL_OP_EVENT
638333149Serj * PF sends this message to inform the VF driver of events that may affect it.
639333149Serj * No direct response is expected from the VF, though it may generate other
640333149Serj * messages in response to this one.
641333149Serj */
642333149Serjenum virtchnl_event_codes {
643333149Serj	VIRTCHNL_EVENT_UNKNOWN = 0,
644333149Serj	VIRTCHNL_EVENT_LINK_CHANGE,
645333149Serj	VIRTCHNL_EVENT_RESET_IMPENDING,
646333149Serj	VIRTCHNL_EVENT_PF_DRIVER_CLOSE,
647333149Serj};
648333149Serj
649333149Serj#define PF_EVENT_SEVERITY_INFO		0
650333149Serj#define PF_EVENT_SEVERITY_ATTENTION	1
651333149Serj#define PF_EVENT_SEVERITY_ACTION_REQUIRED	2
652333149Serj#define PF_EVENT_SEVERITY_CERTAIN_DOOM	255
653333149Serj
654333149Serjstruct virtchnl_pf_event {
655333149Serj	enum virtchnl_event_codes event;
656333149Serj	union {
657349163Serj		/* If the PF driver does not support the new speed reporting
658349163Serj		 * capabilities then use link_event else use link_event_adv to
659349163Serj		 * get the speed and link information. The ability to understand
660349163Serj		 * new speeds is indicated by setting the capability flag
661349163Serj		 * VIRTCHNL_VF_CAP_ADV_LINK_SPEED in vf_cap_flags parameter
662349163Serj		 * in virtchnl_vf_resource struct and can be used to determine
663349163Serj		 * which link event struct to use below.
664349163Serj		 */
665333149Serj		struct {
666333149Serj			enum virtchnl_link_speed link_speed;
667349163Serj			u8 link_status;
668333149Serj		} link_event;
669349163Serj		struct {
670349163Serj			/* link_speed provided in Mbps */
671349163Serj			u32 link_speed;
672349163Serj			u8 link_status;
673349163Serj		} link_event_adv;
674333149Serj	} event_data;
675333149Serj
676333149Serj	int severity;
677333149Serj};
678333149Serj
679333149SerjVIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_pf_event);
680333149Serj
681333149Serj
682333149Serj/* VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP
683333149Serj * VF uses this message to request PF to map IWARP vectors to IWARP queues.
684333149Serj * The request for this originates from the VF IWARP driver through
685333149Serj * a client interface between VF LAN and VF IWARP driver.
686333149Serj * A vector could have an AEQ and CEQ attached to it although
687333149Serj * there is a single AEQ per VF IWARP instance in which case
688333149Serj * most vectors will have an INVALID_IDX for aeq and valid idx for ceq.
689333149Serj * There will never be a case where there will be multiple CEQs attached
690333149Serj * to a single vector.
691333149Serj * PF configures interrupt mapping and returns status.
692333149Serj */
693333149Serjstruct virtchnl_iwarp_qv_info {
694333149Serj	u32 v_idx; /* msix_vector */
695333149Serj	u16 ceq_idx;
696333149Serj	u16 aeq_idx;
697333149Serj	u8 itr_idx;
698333149Serj};
699333149Serj
700333149SerjVIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_iwarp_qv_info);
701333149Serj
702333149Serjstruct virtchnl_iwarp_qvlist_info {
703333149Serj	u32 num_vectors;
704333149Serj	struct virtchnl_iwarp_qv_info qv_info[1];
705333149Serj};
706333149Serj
707333149SerjVIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_iwarp_qvlist_info);
708333149Serj
709333149Serj
710349163Serj/* Since VF messages are limited by u16 size, precalculate the maximum possible
711349163Serj * values of nested elements in virtchnl structures that virtual channel can
712349163Serj * possibly handle in a single message.
713349163Serj */
714349163Serjenum virtchnl_vector_limits {
715349163Serj	VIRTCHNL_OP_CONFIG_VSI_QUEUES_MAX	=
716349163Serj		((u16)(~0) - sizeof(struct virtchnl_vsi_queue_config_info)) /
717349163Serj		sizeof(struct virtchnl_queue_pair_info),
718349163Serj
719349163Serj	VIRTCHNL_OP_CONFIG_IRQ_MAP_MAX		=
720349163Serj		((u16)(~0) - sizeof(struct virtchnl_irq_map_info)) /
721349163Serj		sizeof(struct virtchnl_vector_map),
722349163Serj
723349163Serj	VIRTCHNL_OP_ADD_DEL_ETH_ADDR_MAX	=
724349163Serj		((u16)(~0) - sizeof(struct virtchnl_ether_addr_list)) /
725349163Serj		sizeof(struct virtchnl_ether_addr),
726349163Serj
727349163Serj	VIRTCHNL_OP_ADD_DEL_VLAN_MAX		=
728349163Serj		((u16)(~0) - sizeof(struct virtchnl_vlan_filter_list)) /
729349163Serj		sizeof(u16),
730349163Serj
731349163Serj	VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP_MAX	=
732349163Serj		((u16)(~0) - sizeof(struct virtchnl_iwarp_qvlist_info)) /
733349163Serj		sizeof(struct virtchnl_iwarp_qv_info),
734349163Serj
735349163Serj	VIRTCHNL_OP_ENABLE_CHANNELS_MAX		=
736349163Serj		((u16)(~0) - sizeof(struct virtchnl_tc_info)) /
737349163Serj		sizeof(struct virtchnl_channel_info),
738349163Serj};
739349163Serj
740333149Serj/* VF reset states - these are written into the RSTAT register:
741333149Serj * VFGEN_RSTAT on the VF
742333149Serj * When the PF initiates a reset, it writes 0
743333149Serj * When the reset is complete, it writes 1
744333149Serj * When the PF detects that the VF has recovered, it writes 2
745333149Serj * VF checks this register periodically to determine if a reset has occurred,
746333149Serj * then polls it to know when the reset is complete.
747333149Serj * If either the PF or VF reads the register while the hardware
748333149Serj * is in a reset state, it will return DEADBEEF, which, when masked
749333149Serj * will result in 3.
750333149Serj */
751333149Serjenum virtchnl_vfr_states {
752333149Serj	VIRTCHNL_VFR_INPROGRESS = 0,
753333149Serj	VIRTCHNL_VFR_COMPLETED,
754333149Serj	VIRTCHNL_VFR_VFACTIVE,
755333149Serj};
756333149Serj
757333149Serj/**
758333149Serj * virtchnl_vc_validate_vf_msg
759333149Serj * @ver: Virtchnl version info
760333149Serj * @v_opcode: Opcode for the message
761333149Serj * @msg: pointer to the msg buffer
762333149Serj * @msglen: msg length
763333149Serj *
764333149Serj * validate msg format against struct for each opcode
765333149Serj */
766333149Serjstatic inline int
767333149Serjvirtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
768333149Serj			    u8 *msg, u16 msglen)
769333149Serj{
770333149Serj	bool err_msg_format = FALSE;
771333149Serj	int valid_len = 0;
772333149Serj
773333149Serj	/* Validate message length. */
774333149Serj	switch (v_opcode) {
775333149Serj	case VIRTCHNL_OP_VERSION:
776333149Serj		valid_len = sizeof(struct virtchnl_version_info);
777333149Serj		break;
778333149Serj	case VIRTCHNL_OP_RESET_VF:
779333149Serj		break;
780333149Serj	case VIRTCHNL_OP_GET_VF_RESOURCES:
781333149Serj		if (VF_IS_V11(ver))
782333149Serj			valid_len = sizeof(u32);
783333149Serj		break;
784333149Serj	case VIRTCHNL_OP_CONFIG_TX_QUEUE:
785333149Serj		valid_len = sizeof(struct virtchnl_txq_info);
786333149Serj		break;
787333149Serj	case VIRTCHNL_OP_CONFIG_RX_QUEUE:
788333149Serj		valid_len = sizeof(struct virtchnl_rxq_info);
789333149Serj		break;
790333149Serj	case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
791333149Serj		valid_len = sizeof(struct virtchnl_vsi_queue_config_info);
792333149Serj		if (msglen >= valid_len) {
793333149Serj			struct virtchnl_vsi_queue_config_info *vqc =
794333149Serj			    (struct virtchnl_vsi_queue_config_info *)msg;
795349163Serj
796349163Serj			if (vqc->num_queue_pairs == 0 || vqc->num_queue_pairs >
797349163Serj			    VIRTCHNL_OP_CONFIG_VSI_QUEUES_MAX) {
798349163Serj				err_msg_format = TRUE;
799349163Serj				break;
800349163Serj			}
801349163Serj
802333149Serj			valid_len += (vqc->num_queue_pairs *
803333149Serj				      sizeof(struct
804333149Serj					     virtchnl_queue_pair_info));
805333149Serj		}
806333149Serj		break;
807333149Serj	case VIRTCHNL_OP_CONFIG_IRQ_MAP:
808333149Serj		valid_len = sizeof(struct virtchnl_irq_map_info);
809333149Serj		if (msglen >= valid_len) {
810333149Serj			struct virtchnl_irq_map_info *vimi =
811333149Serj			    (struct virtchnl_irq_map_info *)msg;
812349163Serj
813349163Serj			if (vimi->num_vectors == 0 || vimi->num_vectors >
814349163Serj			    VIRTCHNL_OP_CONFIG_IRQ_MAP_MAX) {
815349163Serj				err_msg_format = TRUE;
816349163Serj				break;
817349163Serj			}
818349163Serj
819333149Serj			valid_len += (vimi->num_vectors *
820333149Serj				      sizeof(struct virtchnl_vector_map));
821333149Serj		}
822333149Serj		break;
823333149Serj	case VIRTCHNL_OP_ENABLE_QUEUES:
824333149Serj	case VIRTCHNL_OP_DISABLE_QUEUES:
825333149Serj		valid_len = sizeof(struct virtchnl_queue_select);
826333149Serj		break;
827333149Serj	case VIRTCHNL_OP_ADD_ETH_ADDR:
828333149Serj	case VIRTCHNL_OP_DEL_ETH_ADDR:
829333149Serj		valid_len = sizeof(struct virtchnl_ether_addr_list);
830333149Serj		if (msglen >= valid_len) {
831333149Serj			struct virtchnl_ether_addr_list *veal =
832333149Serj			    (struct virtchnl_ether_addr_list *)msg;
833349163Serj
834349163Serj			if (veal->num_elements == 0 || veal->num_elements >
835349163Serj			    VIRTCHNL_OP_ADD_DEL_ETH_ADDR_MAX) {
836349163Serj				err_msg_format = TRUE;
837349163Serj				break;
838349163Serj			}
839349163Serj
840333149Serj			valid_len += veal->num_elements *
841333149Serj			    sizeof(struct virtchnl_ether_addr);
842333149Serj		}
843333149Serj		break;
844333149Serj	case VIRTCHNL_OP_ADD_VLAN:
845333149Serj	case VIRTCHNL_OP_DEL_VLAN:
846333149Serj		valid_len = sizeof(struct virtchnl_vlan_filter_list);
847333149Serj		if (msglen >= valid_len) {
848333149Serj			struct virtchnl_vlan_filter_list *vfl =
849333149Serj			    (struct virtchnl_vlan_filter_list *)msg;
850349163Serj
851349163Serj			if (vfl->num_elements == 0 || vfl->num_elements >
852349163Serj			    VIRTCHNL_OP_ADD_DEL_VLAN_MAX) {
853349163Serj				err_msg_format = TRUE;
854349163Serj				break;
855349163Serj			}
856349163Serj
857333149Serj			valid_len += vfl->num_elements * sizeof(u16);
858333149Serj		}
859333149Serj		break;
860333149Serj	case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
861333149Serj		valid_len = sizeof(struct virtchnl_promisc_info);
862333149Serj		break;
863333149Serj	case VIRTCHNL_OP_GET_STATS:
864333149Serj		valid_len = sizeof(struct virtchnl_queue_select);
865333149Serj		break;
866333149Serj	case VIRTCHNL_OP_IWARP:
867333149Serj		/* These messages are opaque to us and will be validated in
868333149Serj		 * the RDMA client code. We just need to check for nonzero
869333149Serj		 * length. The firmware will enforce max length restrictions.
870333149Serj		 */
871333149Serj		if (msglen)
872333149Serj			valid_len = msglen;
873333149Serj		else
874333149Serj			err_msg_format = TRUE;
875333149Serj		break;
876333149Serj	case VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP:
877333149Serj		break;
878333149Serj	case VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP:
879333149Serj		valid_len = sizeof(struct virtchnl_iwarp_qvlist_info);
880333149Serj		if (msglen >= valid_len) {
881333149Serj			struct virtchnl_iwarp_qvlist_info *qv =
882333149Serj				(struct virtchnl_iwarp_qvlist_info *)msg;
883349163Serj
884349163Serj			if (qv->num_vectors == 0 || qv->num_vectors >
885349163Serj			    VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP_MAX) {
886333149Serj				err_msg_format = TRUE;
887333149Serj				break;
888333149Serj			}
889349163Serj
890333149Serj			valid_len += ((qv->num_vectors - 1) *
891333149Serj				sizeof(struct virtchnl_iwarp_qv_info));
892333149Serj		}
893333149Serj		break;
894333149Serj	case VIRTCHNL_OP_CONFIG_RSS_KEY:
895333149Serj		valid_len = sizeof(struct virtchnl_rss_key);
896333149Serj		if (msglen >= valid_len) {
897333149Serj			struct virtchnl_rss_key *vrk =
898333149Serj				(struct virtchnl_rss_key *)msg;
899333149Serj			valid_len += vrk->key_len - 1;
900333149Serj		}
901333149Serj		break;
902333149Serj	case VIRTCHNL_OP_CONFIG_RSS_LUT:
903333149Serj		valid_len = sizeof(struct virtchnl_rss_lut);
904333149Serj		if (msglen >= valid_len) {
905333149Serj			struct virtchnl_rss_lut *vrl =
906333149Serj				(struct virtchnl_rss_lut *)msg;
907333149Serj			valid_len += vrl->lut_entries - 1;
908333149Serj		}
909333149Serj		break;
910333149Serj	case VIRTCHNL_OP_GET_RSS_HENA_CAPS:
911333149Serj		break;
912333149Serj	case VIRTCHNL_OP_SET_RSS_HENA:
913333149Serj		valid_len = sizeof(struct virtchnl_rss_hena);
914333149Serj		break;
915333149Serj	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
916333149Serj	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
917333149Serj		break;
918333149Serj	case VIRTCHNL_OP_REQUEST_QUEUES:
919333149Serj		valid_len = sizeof(struct virtchnl_vf_res_request);
920333149Serj		break;
921349163Serj	case VIRTCHNL_OP_ENABLE_CHANNELS:
922349163Serj		valid_len = sizeof(struct virtchnl_tc_info);
923349163Serj		if (msglen >= valid_len) {
924349163Serj			struct virtchnl_tc_info *vti =
925349163Serj				(struct virtchnl_tc_info *)msg;
926349163Serj
927349163Serj			if (vti->num_tc == 0 || vti->num_tc >
928349163Serj			    VIRTCHNL_OP_ENABLE_CHANNELS_MAX) {
929349163Serj				err_msg_format = TRUE;
930349163Serj				break;
931349163Serj			}
932349163Serj
933349163Serj			valid_len += (vti->num_tc - 1) *
934349163Serj				     sizeof(struct virtchnl_channel_info);
935349163Serj		}
936349163Serj		break;
937349163Serj	case VIRTCHNL_OP_DISABLE_CHANNELS:
938349163Serj		break;
939349163Serj	case VIRTCHNL_OP_ADD_CLOUD_FILTER:
940349163Serj		/* fall through */
941349163Serj	case VIRTCHNL_OP_DEL_CLOUD_FILTER:
942349163Serj		valid_len = sizeof(struct virtchnl_filter);
943349163Serj		break;
944333149Serj	/* These are always errors coming from the VF. */
945333149Serj	case VIRTCHNL_OP_EVENT:
946333149Serj	case VIRTCHNL_OP_UNKNOWN:
947333149Serj	default:
948349163Serj		return VIRTCHNL_STATUS_ERR_PARAM;
949333149Serj	}
950333149Serj	/* few more checks */
951333149Serj	if (err_msg_format || valid_len != msglen)
952333149Serj		return VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH;
953333149Serj
954333149Serj	return 0;
955333149Serj}
956333149Serj#endif /* _VIRTCHNL_H_ */
957