|  | /* SPDX-License-Identifier: GPL-2.0-only */ | 
|  | /******************************************************************************* | 
|  | * | 
|  | * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver | 
|  | * Copyright(c) 2013 - 2014 Intel Corporation. | 
|  | * | 
|  | * Contact Information: | 
|  | * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | 
|  | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 
|  | * | 
|  | ******************************************************************************/ | 
|  |  | 
|  | #ifndef _VIRTCHNL_H_ | 
|  | #define _VIRTCHNL_H_ | 
|  |  | 
|  | /* Description: | 
|  | * This header file describes the VF-PF communication protocol used | 
|  | * by the drivers for all devices starting from our 40G product line | 
|  | * | 
|  | * Admin queue buffer usage: | 
|  | * desc->opcode is always aqc_opc_send_msg_to_pf | 
|  | * flags, retval, datalen, and data addr are all used normally. | 
|  | * The Firmware copies the cookie fields when sending messages between the | 
|  | * PF and VF, but uses all other fields internally. Due to this limitation, | 
|  | * we must send all messages as "indirect", i.e. using an external buffer. | 
|  | * | 
|  | * All the VSI indexes are relative to the VF. Each VF can have maximum of | 
|  | * three VSIs. All the queue indexes are relative to the VSI.  Each VF can | 
|  | * have a maximum of sixteen queues for all of its VSIs. | 
|  | * | 
|  | * The PF is required to return a status code in v_retval for all messages | 
|  | * except RESET_VF, which does not require any response. The return value | 
|  | * is of status_code type, defined in the shared type.h. | 
|  | * | 
|  | * In general, VF driver initialization should roughly follow the order of | 
|  | * these opcodes. The VF driver must first validate the API version of the | 
|  | * PF driver, then request a reset, then get resources, then configure | 
|  | * queues and interrupts. After these operations are complete, the VF | 
|  | * driver may start its queues, optionally add MAC and VLAN filters, and | 
|  | * process traffic. | 
|  | */ | 
|  |  | 
|  | /* START GENERIC DEFINES | 
|  | * Need to ensure the following enums and defines hold the same meaning and | 
|  | * value in current and future projects | 
|  | */ | 
|  |  | 
|  | /* Error Codes */ | 
|  | enum virtchnl_status_code { | 
|  | VIRTCHNL_STATUS_SUCCESS				= 0, | 
|  | VIRTCHNL_STATUS_ERR_PARAM			= -5, | 
|  | VIRTCHNL_STATUS_ERR_NO_MEMORY			= -18, | 
|  | VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH		= -38, | 
|  | VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR		= -39, | 
|  | VIRTCHNL_STATUS_ERR_INVALID_VF_ID		= -40, | 
|  | VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR		= -53, | 
|  | VIRTCHNL_STATUS_ERR_NOT_SUPPORTED		= -64, | 
|  | }; | 
|  |  | 
|  | /* Backward compatibility */ | 
|  | #define VIRTCHNL_ERR_PARAM VIRTCHNL_STATUS_ERR_PARAM | 
|  | #define VIRTCHNL_STATUS_NOT_SUPPORTED VIRTCHNL_STATUS_ERR_NOT_SUPPORTED | 
|  |  | 
|  | #define VIRTCHNL_LINK_SPEED_2_5GB_SHIFT		0x0 | 
|  | #define VIRTCHNL_LINK_SPEED_100MB_SHIFT		0x1 | 
|  | #define VIRTCHNL_LINK_SPEED_1000MB_SHIFT	0x2 | 
|  | #define VIRTCHNL_LINK_SPEED_10GB_SHIFT		0x3 | 
|  | #define VIRTCHNL_LINK_SPEED_40GB_SHIFT		0x4 | 
|  | #define VIRTCHNL_LINK_SPEED_20GB_SHIFT		0x5 | 
|  | #define VIRTCHNL_LINK_SPEED_25GB_SHIFT		0x6 | 
|  | #define VIRTCHNL_LINK_SPEED_5GB_SHIFT		0x7 | 
|  |  | 
|  | enum virtchnl_link_speed { | 
|  | VIRTCHNL_LINK_SPEED_UNKNOWN	= 0, | 
|  | VIRTCHNL_LINK_SPEED_100MB	= BIT(VIRTCHNL_LINK_SPEED_100MB_SHIFT), | 
|  | VIRTCHNL_LINK_SPEED_1GB		= BIT(VIRTCHNL_LINK_SPEED_1000MB_SHIFT), | 
|  | VIRTCHNL_LINK_SPEED_10GB	= BIT(VIRTCHNL_LINK_SPEED_10GB_SHIFT), | 
|  | VIRTCHNL_LINK_SPEED_40GB	= BIT(VIRTCHNL_LINK_SPEED_40GB_SHIFT), | 
|  | VIRTCHNL_LINK_SPEED_20GB	= BIT(VIRTCHNL_LINK_SPEED_20GB_SHIFT), | 
|  | VIRTCHNL_LINK_SPEED_25GB	= BIT(VIRTCHNL_LINK_SPEED_25GB_SHIFT), | 
|  | VIRTCHNL_LINK_SPEED_2_5GB	= BIT(VIRTCHNL_LINK_SPEED_2_5GB_SHIFT), | 
|  | VIRTCHNL_LINK_SPEED_5GB		= BIT(VIRTCHNL_LINK_SPEED_5GB_SHIFT), | 
|  | }; | 
|  |  | 
|  | /* for hsplit_0 field of Rx HMC context */ | 
|  | /* deprecated with AVF 1.0 */ | 
|  | enum virtchnl_rx_hsplit { | 
|  | VIRTCHNL_RX_HSPLIT_NO_SPLIT      = 0, | 
|  | VIRTCHNL_RX_HSPLIT_SPLIT_L2      = 1, | 
|  | VIRTCHNL_RX_HSPLIT_SPLIT_IP      = 2, | 
|  | VIRTCHNL_RX_HSPLIT_SPLIT_TCP_UDP = 4, | 
|  | VIRTCHNL_RX_HSPLIT_SPLIT_SCTP    = 8, | 
|  | }; | 
|  |  | 
|  | /* END GENERIC DEFINES */ | 
|  |  | 
|  | /* Opcodes for VF-PF communication. These are placed in the v_opcode field | 
|  | * of the virtchnl_msg structure. | 
|  | */ | 
|  | enum virtchnl_ops { | 
|  | /* The PF sends status change events to VFs using | 
|  | * the VIRTCHNL_OP_EVENT opcode. | 
|  | * VFs send requests to the PF using the other ops. | 
|  | * Use of "advanced opcode" features must be negotiated as part of capabilities | 
|  | * exchange and are not considered part of base mode feature set. | 
|  | */ | 
|  | VIRTCHNL_OP_UNKNOWN = 0, | 
|  | VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */ | 
|  | VIRTCHNL_OP_RESET_VF = 2, | 
|  | VIRTCHNL_OP_GET_VF_RESOURCES = 3, | 
|  | VIRTCHNL_OP_CONFIG_TX_QUEUE = 4, | 
|  | VIRTCHNL_OP_CONFIG_RX_QUEUE = 5, | 
|  | VIRTCHNL_OP_CONFIG_VSI_QUEUES = 6, | 
|  | VIRTCHNL_OP_CONFIG_IRQ_MAP = 7, | 
|  | VIRTCHNL_OP_ENABLE_QUEUES = 8, | 
|  | VIRTCHNL_OP_DISABLE_QUEUES = 9, | 
|  | VIRTCHNL_OP_ADD_ETH_ADDR = 10, | 
|  | VIRTCHNL_OP_DEL_ETH_ADDR = 11, | 
|  | VIRTCHNL_OP_ADD_VLAN = 12, | 
|  | VIRTCHNL_OP_DEL_VLAN = 13, | 
|  | VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14, | 
|  | VIRTCHNL_OP_GET_STATS = 15, | 
|  | VIRTCHNL_OP_RSVD = 16, | 
|  | VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */ | 
|  | VIRTCHNL_OP_IWARP = 20, /* advanced opcode */ | 
|  | VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21, /* advanced opcode */ | 
|  | VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP = 22, /* advanced opcode */ | 
|  | VIRTCHNL_OP_CONFIG_RSS_KEY = 23, | 
|  | VIRTCHNL_OP_CONFIG_RSS_LUT = 24, | 
|  | VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25, | 
|  | VIRTCHNL_OP_SET_RSS_HENA = 26, | 
|  | VIRTCHNL_OP_ENABLE_VLAN_STRIPPING = 27, | 
|  | VIRTCHNL_OP_DISABLE_VLAN_STRIPPING = 28, | 
|  | VIRTCHNL_OP_REQUEST_QUEUES = 29, | 
|  | VIRTCHNL_OP_ENABLE_CHANNELS = 30, | 
|  | VIRTCHNL_OP_DISABLE_CHANNELS = 31, | 
|  | VIRTCHNL_OP_ADD_CLOUD_FILTER = 32, | 
|  | VIRTCHNL_OP_DEL_CLOUD_FILTER = 33, | 
|  | }; | 
|  |  | 
|  | /* These macros are used to generate compilation errors if a structure/union | 
|  | * is not exactly the correct length. It gives a divide by zero error if the | 
|  | * structure/union is not of the correct size, otherwise it creates an enum | 
|  | * that is never used. | 
|  | */ | 
|  | #define VIRTCHNL_CHECK_STRUCT_LEN(n, X) enum virtchnl_static_assert_enum_##X \ | 
|  | { virtchnl_static_assert_##X = (n)/((sizeof(struct X) == (n)) ? 1 : 0) } | 
|  | #define VIRTCHNL_CHECK_UNION_LEN(n, X) enum virtchnl_static_asset_enum_##X \ | 
|  | { virtchnl_static_assert_##X = (n)/((sizeof(union X) == (n)) ? 1 : 0) } | 
|  |  | 
|  | /* Virtual channel message descriptor. This overlays the admin queue | 
|  | * descriptor. All other data is passed in external buffers. | 
|  | */ | 
|  |  | 
|  | struct virtchnl_msg { | 
|  | u8 pad[8];			 /* AQ flags/opcode/len/retval fields */ | 
|  | enum virtchnl_ops v_opcode; /* avoid confusion with desc->opcode */ | 
|  | enum virtchnl_status_code v_retval;  /* ditto for desc->retval */ | 
|  | u32 vfid;			 /* used by PF when sending to VF */ | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(20, virtchnl_msg); | 
|  |  | 
|  | /* Message descriptions and data structures. */ | 
|  |  | 
|  | /* VIRTCHNL_OP_VERSION | 
|  | * VF posts its version number to the PF. PF responds with its version number | 
|  | * in the same format, along with a return code. | 
|  | * Reply from PF has its major/minor versions also in param0 and param1. | 
|  | * If there is a major version mismatch, then the VF cannot operate. | 
|  | * If there is a minor version mismatch, then the VF can operate but should | 
|  | * add a warning to the system log. | 
|  | * | 
|  | * This enum element MUST always be specified as == 1, regardless of other | 
|  | * changes in the API. The PF must always respond to this message without | 
|  | * error regardless of version mismatch. | 
|  | */ | 
|  | #define VIRTCHNL_VERSION_MAJOR		1 | 
|  | #define VIRTCHNL_VERSION_MINOR		1 | 
|  | #define VIRTCHNL_VERSION_MINOR_NO_VF_CAPS	0 | 
|  |  | 
|  | struct virtchnl_version_info { | 
|  | u32 major; | 
|  | u32 minor; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_version_info); | 
|  |  | 
|  | #define VF_IS_V10(_v) (((_v)->major == 1) && ((_v)->minor == 0)) | 
|  | #define VF_IS_V11(_ver) (((_ver)->major == 1) && ((_ver)->minor == 1)) | 
|  |  | 
|  | /* VIRTCHNL_OP_RESET_VF | 
|  | * VF sends this request to PF with no parameters | 
|  | * PF does NOT respond! VF driver must delay then poll VFGEN_RSTAT register | 
|  | * until reset completion is indicated. The admin queue must be reinitialized | 
|  | * after this operation. | 
|  | * | 
|  | * When reset is complete, PF must ensure that all queues in all VSIs associated | 
|  | * with the VF are stopped, all queue configurations in the HMC are set to 0, | 
|  | * and all MAC and VLAN filters (except the default MAC address) on all VSIs | 
|  | * are cleared. | 
|  | */ | 
|  |  | 
|  | /* VSI types that use VIRTCHNL interface for VF-PF communication. VSI_SRIOV | 
|  | * vsi_type should always be 6 for backward compatibility. Add other fields | 
|  | * as needed. | 
|  | */ | 
|  | enum virtchnl_vsi_type { | 
|  | VIRTCHNL_VSI_TYPE_INVALID = 0, | 
|  | VIRTCHNL_VSI_SRIOV = 6, | 
|  | }; | 
|  |  | 
|  | /* VIRTCHNL_OP_GET_VF_RESOURCES | 
|  | * Version 1.0 VF sends this request to PF with no parameters | 
|  | * Version 1.1 VF sends this request to PF with u32 bitmap of its capabilities | 
|  | * PF responds with an indirect message containing | 
|  | * virtchnl_vf_resource and one or more | 
|  | * virtchnl_vsi_resource structures. | 
|  | */ | 
|  |  | 
|  | struct virtchnl_vsi_resource { | 
|  | u16 vsi_id; | 
|  | u16 num_queue_pairs; | 
|  | enum virtchnl_vsi_type vsi_type; | 
|  | u16 qset_handle; | 
|  | u8 default_mac_addr[ETH_ALEN]; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource); | 
|  |  | 
|  | /* VF capability flags | 
|  | * VIRTCHNL_VF_OFFLOAD_L2 flag is inclusive of base mode L2 offloads including | 
|  | * TX/RX Checksum offloading and TSO for non-tunnelled packets. | 
|  | */ | 
|  | #define VIRTCHNL_VF_OFFLOAD_L2			0x00000001 | 
|  | #define VIRTCHNL_VF_OFFLOAD_IWARP		0x00000002 | 
|  | #define VIRTCHNL_VF_OFFLOAD_RSVD		0x00000004 | 
|  | #define VIRTCHNL_VF_OFFLOAD_RSS_AQ		0x00000008 | 
|  | #define VIRTCHNL_VF_OFFLOAD_RSS_REG		0x00000010 | 
|  | #define VIRTCHNL_VF_OFFLOAD_WB_ON_ITR		0x00000020 | 
|  | #define VIRTCHNL_VF_OFFLOAD_REQ_QUEUES		0x00000040 | 
|  | #define VIRTCHNL_VF_OFFLOAD_VLAN		0x00010000 | 
|  | #define VIRTCHNL_VF_OFFLOAD_RX_POLLING		0x00020000 | 
|  | #define VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2	0x00040000 | 
|  | #define VIRTCHNL_VF_OFFLOAD_RSS_PF		0X00080000 | 
|  | #define VIRTCHNL_VF_OFFLOAD_ENCAP		0X00100000 | 
|  | #define VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM		0X00200000 | 
|  | #define VIRTCHNL_VF_OFFLOAD_RX_ENCAP_CSUM	0X00400000 | 
|  | #define VIRTCHNL_VF_OFFLOAD_ADQ			0X00800000 | 
|  |  | 
|  | /* Define below the capability flags that are not offloads */ | 
|  | #define VIRTCHNL_VF_CAP_ADV_LINK_SPEED		0x00000080 | 
|  | #define VF_BASE_MODE_OFFLOADS (VIRTCHNL_VF_OFFLOAD_L2 | \ | 
|  | VIRTCHNL_VF_OFFLOAD_VLAN | \ | 
|  | VIRTCHNL_VF_OFFLOAD_RSS_PF) | 
|  |  | 
|  | struct virtchnl_vf_resource { | 
|  | u16 num_vsis; | 
|  | u16 num_queue_pairs; | 
|  | u16 max_vectors; | 
|  | u16 max_mtu; | 
|  |  | 
|  | u32 vf_cap_flags; | 
|  | u32 rss_key_size; | 
|  | u32 rss_lut_size; | 
|  |  | 
|  | struct virtchnl_vsi_resource vsi_res[1]; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(36, virtchnl_vf_resource); | 
|  |  | 
|  | /* VIRTCHNL_OP_CONFIG_TX_QUEUE | 
|  | * VF sends this message to set up parameters for one TX queue. | 
|  | * External data buffer contains one instance of virtchnl_txq_info. | 
|  | * PF configures requested queue and returns a status code. | 
|  | */ | 
|  |  | 
|  | /* Tx queue config info */ | 
|  | struct virtchnl_txq_info { | 
|  | u16 vsi_id; | 
|  | u16 queue_id; | 
|  | u16 ring_len;		/* number of descriptors, multiple of 8 */ | 
|  | u16 headwb_enabled; /* deprecated with AVF 1.0 */ | 
|  | u64 dma_ring_addr; | 
|  | u64 dma_headwb_addr; /* deprecated with AVF 1.0 */ | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_txq_info); | 
|  |  | 
|  | /* VIRTCHNL_OP_CONFIG_RX_QUEUE | 
|  | * VF sends this message to set up parameters for one RX queue. | 
|  | * External data buffer contains one instance of virtchnl_rxq_info. | 
|  | * PF configures requested queue and returns a status code. | 
|  | */ | 
|  |  | 
|  | /* Rx queue config info */ | 
|  | struct virtchnl_rxq_info { | 
|  | u16 vsi_id; | 
|  | u16 queue_id; | 
|  | u32 ring_len;		/* number of descriptors, multiple of 32 */ | 
|  | u16 hdr_size; | 
|  | u16 splithdr_enabled; /* deprecated with AVF 1.0 */ | 
|  | u32 databuffer_size; | 
|  | u32 max_pkt_size; | 
|  | u32 pad1; | 
|  | u64 dma_ring_addr; | 
|  | enum virtchnl_rx_hsplit rx_split_pos; /* deprecated with AVF 1.0 */ | 
|  | u32 pad2; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(40, virtchnl_rxq_info); | 
|  |  | 
|  | /* VIRTCHNL_OP_CONFIG_VSI_QUEUES | 
|  | * VF sends this message to set parameters for all active TX and RX queues | 
|  | * associated with the specified VSI. | 
|  | * PF configures queues and returns status. | 
|  | * If the number of queues specified is greater than the number of queues | 
|  | * associated with the VSI, an error is returned and no queues are configured. | 
|  | */ | 
|  | struct virtchnl_queue_pair_info { | 
|  | /* NOTE: vsi_id and queue_id should be identical for both queues. */ | 
|  | struct virtchnl_txq_info txq; | 
|  | struct virtchnl_rxq_info rxq; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(64, virtchnl_queue_pair_info); | 
|  |  | 
|  | struct virtchnl_vsi_queue_config_info { | 
|  | u16 vsi_id; | 
|  | u16 num_queue_pairs; | 
|  | u32 pad; | 
|  | struct virtchnl_queue_pair_info qpair[1]; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(72, virtchnl_vsi_queue_config_info); | 
|  |  | 
|  | /* VIRTCHNL_OP_REQUEST_QUEUES | 
|  | * VF sends this message to request the PF to allocate additional queues to | 
|  | * this VF.  Each VF gets a guaranteed number of queues on init but asking for | 
|  | * additional queues must be negotiated.  This is a best effort request as it | 
|  | * is possible the PF does not have enough queues left to support the request. | 
|  | * If the PF cannot support the number requested it will respond with the | 
|  | * maximum number it is able to support.  If the request is successful, PF will | 
|  | * then reset the VF to institute required changes. | 
|  | */ | 
|  |  | 
|  | /* VF resource request */ | 
|  | struct virtchnl_vf_res_request { | 
|  | u16 num_queue_pairs; | 
|  | }; | 
|  |  | 
|  | /* VIRTCHNL_OP_CONFIG_IRQ_MAP | 
|  | * VF uses this message to map vectors to queues. | 
|  | * The rxq_map and txq_map fields are bitmaps used to indicate which queues | 
|  | * are to be associated with the specified vector. | 
|  | * The "other" causes are always mapped to vector 0. | 
|  | * PF configures interrupt mapping and returns status. | 
|  | */ | 
|  | struct virtchnl_vector_map { | 
|  | u16 vsi_id; | 
|  | u16 vector_id; | 
|  | u16 rxq_map; | 
|  | u16 txq_map; | 
|  | u16 rxitr_idx; | 
|  | u16 txitr_idx; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_vector_map); | 
|  |  | 
|  | struct virtchnl_irq_map_info { | 
|  | u16 num_vectors; | 
|  | struct virtchnl_vector_map vecmap[1]; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(14, virtchnl_irq_map_info); | 
|  |  | 
|  | /* VIRTCHNL_OP_ENABLE_QUEUES | 
|  | * VIRTCHNL_OP_DISABLE_QUEUES | 
|  | * VF sends these message to enable or disable TX/RX queue pairs. | 
|  | * The queues fields are bitmaps indicating which queues to act upon. | 
|  | * (Currently, we only support 16 queues per VF, but we make the field | 
|  | * u32 to allow for expansion.) | 
|  | * PF performs requested action and returns status. | 
|  | */ | 
|  | struct virtchnl_queue_select { | 
|  | u16 vsi_id; | 
|  | u16 pad; | 
|  | u32 rx_queues; | 
|  | u32 tx_queues; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_queue_select); | 
|  |  | 
|  | /* VIRTCHNL_OP_ADD_ETH_ADDR | 
|  | * VF sends this message in order to add one or more unicast or multicast | 
|  | * address filters for the specified VSI. | 
|  | * PF adds the filters and returns status. | 
|  | */ | 
|  |  | 
|  | /* VIRTCHNL_OP_DEL_ETH_ADDR | 
|  | * VF sends this message in order to remove one or more unicast or multicast | 
|  | * filters for the specified VSI. | 
|  | * PF removes the filters and returns status. | 
|  | */ | 
|  |  | 
|  | struct virtchnl_ether_addr { | 
|  | u8 addr[ETH_ALEN]; | 
|  | u8 pad[2]; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_ether_addr); | 
|  |  | 
|  | struct virtchnl_ether_addr_list { | 
|  | u16 vsi_id; | 
|  | u16 num_elements; | 
|  | struct virtchnl_ether_addr list[1]; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_ether_addr_list); | 
|  |  | 
|  | /* VIRTCHNL_OP_ADD_VLAN | 
|  | * VF sends this message to add one or more VLAN tag filters for receives. | 
|  | * PF adds the filters and returns status. | 
|  | * If a port VLAN is configured by the PF, this operation will return an | 
|  | * error to the VF. | 
|  | */ | 
|  |  | 
|  | /* VIRTCHNL_OP_DEL_VLAN | 
|  | * VF sends this message to remove one or more VLAN tag filters for receives. | 
|  | * PF removes the filters and returns status. | 
|  | * If a port VLAN is configured by the PF, this operation will return an | 
|  | * error to the VF. | 
|  | */ | 
|  |  | 
|  | struct virtchnl_vlan_filter_list { | 
|  | u16 vsi_id; | 
|  | u16 num_elements; | 
|  | u16 vlan_id[1]; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_vlan_filter_list); | 
|  |  | 
|  | /* VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE | 
|  | * VF sends VSI id and flags. | 
|  | * PF returns status code in retval. | 
|  | * Note: we assume that broadcast accept mode is always enabled. | 
|  | */ | 
|  | struct virtchnl_promisc_info { | 
|  | u16 vsi_id; | 
|  | u16 flags; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(4, virtchnl_promisc_info); | 
|  |  | 
|  | #define FLAG_VF_UNICAST_PROMISC	0x00000001 | 
|  | #define FLAG_VF_MULTICAST_PROMISC	0x00000002 | 
|  |  | 
|  | /* VIRTCHNL_OP_GET_STATS | 
|  | * VF sends this message to request stats for the selected VSI. VF uses | 
|  | * the virtchnl_queue_select struct to specify the VSI. The queue_id | 
|  | * field is ignored by the PF. | 
|  | * | 
|  | * PF replies with struct eth_stats in an external buffer. | 
|  | */ | 
|  |  | 
|  | /* VIRTCHNL_OP_CONFIG_RSS_KEY | 
|  | * VIRTCHNL_OP_CONFIG_RSS_LUT | 
|  | * VF sends these messages to configure RSS. Only supported if both PF | 
|  | * and VF drivers set the VIRTCHNL_VF_OFFLOAD_RSS_PF bit during | 
|  | * configuration negotiation. If this is the case, then the RSS fields in | 
|  | * the VF resource struct are valid. | 
|  | * Both the key and LUT are initialized to 0 by the PF, meaning that | 
|  | * RSS is effectively disabled until set up by the VF. | 
|  | */ | 
|  | struct virtchnl_rss_key { | 
|  | u16 vsi_id; | 
|  | u16 key_len; | 
|  | u8 key[1];         /* RSS hash key, packed bytes */ | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_key); | 
|  |  | 
|  | struct virtchnl_rss_lut { | 
|  | u16 vsi_id; | 
|  | u16 lut_entries; | 
|  | u8 lut[1];        /* RSS lookup table */ | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_lut); | 
|  |  | 
|  | /* VIRTCHNL_OP_GET_RSS_HENA_CAPS | 
|  | * VIRTCHNL_OP_SET_RSS_HENA | 
|  | * VF sends these messages to get and set the hash filter enable bits for RSS. | 
|  | * By default, the PF sets these to all possible traffic types that the | 
|  | * hardware supports. The VF can query this value if it wants to change the | 
|  | * traffic types that are hashed by the hardware. | 
|  | */ | 
|  | struct virtchnl_rss_hena { | 
|  | u64 hena; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_rss_hena); | 
|  |  | 
|  | /* VIRTCHNL_OP_ENABLE_CHANNELS | 
|  | * VIRTCHNL_OP_DISABLE_CHANNELS | 
|  | * VF sends these messages to enable or disable channels based on | 
|  | * the user specified queue count and queue offset for each traffic class. | 
|  | * This struct encompasses all the information that the PF needs from | 
|  | * VF to create a channel. | 
|  | */ | 
|  | struct virtchnl_channel_info { | 
|  | u16 count; /* number of queues in a channel */ | 
|  | u16 offset; /* queues in a channel start from 'offset' */ | 
|  | u32 pad; | 
|  | u64 max_tx_rate; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_channel_info); | 
|  |  | 
|  | struct virtchnl_tc_info { | 
|  | u32	num_tc; | 
|  | u32	pad; | 
|  | struct	virtchnl_channel_info list[1]; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_tc_info); | 
|  |  | 
|  | /* VIRTCHNL_ADD_CLOUD_FILTER | 
|  | * VIRTCHNL_DEL_CLOUD_FILTER | 
|  | * VF sends these messages to add or delete a cloud filter based on the | 
|  | * user specified match and action filters. These structures encompass | 
|  | * all the information that the PF needs from the VF to add/delete a | 
|  | * cloud filter. | 
|  | */ | 
|  |  | 
|  | struct virtchnl_l4_spec { | 
|  | u8	src_mac[ETH_ALEN]; | 
|  | u8	dst_mac[ETH_ALEN]; | 
|  | __be16	vlan_id; | 
|  | __be16	pad; /* reserved for future use */ | 
|  | __be32	src_ip[4]; | 
|  | __be32	dst_ip[4]; | 
|  | __be16	src_port; | 
|  | __be16	dst_port; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(52, virtchnl_l4_spec); | 
|  |  | 
|  | union virtchnl_flow_spec { | 
|  | struct	virtchnl_l4_spec tcp_spec; | 
|  | u8	buffer[128]; /* reserved for future use */ | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_UNION_LEN(128, virtchnl_flow_spec); | 
|  |  | 
|  | enum virtchnl_action { | 
|  | /* action types */ | 
|  | VIRTCHNL_ACTION_DROP = 0, | 
|  | VIRTCHNL_ACTION_TC_REDIRECT, | 
|  | }; | 
|  |  | 
|  | enum virtchnl_flow_type { | 
|  | /* flow types */ | 
|  | VIRTCHNL_TCP_V4_FLOW = 0, | 
|  | VIRTCHNL_TCP_V6_FLOW, | 
|  | }; | 
|  |  | 
|  | struct virtchnl_filter { | 
|  | union	virtchnl_flow_spec data; | 
|  | union	virtchnl_flow_spec mask; | 
|  | enum	virtchnl_flow_type flow_type; | 
|  | enum	virtchnl_action action; | 
|  | u32	action_meta; | 
|  | u8	field_flags; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(272, virtchnl_filter); | 
|  |  | 
|  | /* VIRTCHNL_OP_EVENT | 
|  | * PF sends this message to inform the VF driver of events that may affect it. | 
|  | * No direct response is expected from the VF, though it may generate other | 
|  | * messages in response to this one. | 
|  | */ | 
|  | enum virtchnl_event_codes { | 
|  | VIRTCHNL_EVENT_UNKNOWN = 0, | 
|  | VIRTCHNL_EVENT_LINK_CHANGE, | 
|  | VIRTCHNL_EVENT_RESET_IMPENDING, | 
|  | VIRTCHNL_EVENT_PF_DRIVER_CLOSE, | 
|  | }; | 
|  |  | 
|  | #define PF_EVENT_SEVERITY_INFO		0 | 
|  | #define PF_EVENT_SEVERITY_CERTAIN_DOOM	255 | 
|  |  | 
|  | struct virtchnl_pf_event { | 
|  | enum virtchnl_event_codes event; | 
|  | union { | 
|  | /* If the PF driver does not support the new speed reporting | 
|  | * capabilities then use link_event else use link_event_adv to | 
|  | * get the speed and link information. The ability to understand | 
|  | * new speeds is indicated by setting the capability flag | 
|  | * VIRTCHNL_VF_CAP_ADV_LINK_SPEED in vf_cap_flags parameter | 
|  | * in virtchnl_vf_resource struct and can be used to determine | 
|  | * which link event struct to use below. | 
|  | */ | 
|  | struct { | 
|  | enum virtchnl_link_speed link_speed; | 
|  | bool link_status; | 
|  | } link_event; | 
|  | struct { | 
|  | /* link_speed provided in Mbps */ | 
|  | u32 link_speed; | 
|  | u8 link_status; | 
|  | } link_event_adv; | 
|  | } event_data; | 
|  |  | 
|  | int severity; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_pf_event); | 
|  |  | 
|  | /* VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP | 
|  | * VF uses this message to request PF to map IWARP vectors to IWARP queues. | 
|  | * The request for this originates from the VF IWARP driver through | 
|  | * a client interface between VF LAN and VF IWARP driver. | 
|  | * A vector could have an AEQ and CEQ attached to it although | 
|  | * there is a single AEQ per VF IWARP instance in which case | 
|  | * most vectors will have an INVALID_IDX for aeq and valid idx for ceq. | 
|  | * There will never be a case where there will be multiple CEQs attached | 
|  | * to a single vector. | 
|  | * PF configures interrupt mapping and returns status. | 
|  | */ | 
|  |  | 
|  | struct virtchnl_iwarp_qv_info { | 
|  | u32 v_idx; /* msix_vector */ | 
|  | u16 ceq_idx; | 
|  | u16 aeq_idx; | 
|  | u8 itr_idx; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_iwarp_qv_info); | 
|  |  | 
|  | struct virtchnl_iwarp_qvlist_info { | 
|  | u32 num_vectors; | 
|  | struct virtchnl_iwarp_qv_info qv_info[1]; | 
|  | }; | 
|  |  | 
|  | VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_iwarp_qvlist_info); | 
|  |  | 
|  | /* VF reset states - these are written into the RSTAT register: | 
|  | * VFGEN_RSTAT on the VF | 
|  | * When the PF initiates a reset, it writes 0 | 
|  | * When the reset is complete, it writes 1 | 
|  | * When the PF detects that the VF has recovered, it writes 2 | 
|  | * VF checks this register periodically to determine if a reset has occurred, | 
|  | * then polls it to know when the reset is complete. | 
|  | * If either the PF or VF reads the register while the hardware | 
|  | * is in a reset state, it will return DEADBEEF, which, when masked | 
|  | * will result in 3. | 
|  | */ | 
|  | enum virtchnl_vfr_states { | 
|  | VIRTCHNL_VFR_INPROGRESS = 0, | 
|  | VIRTCHNL_VFR_COMPLETED, | 
|  | VIRTCHNL_VFR_VFACTIVE, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * virtchnl_vc_validate_vf_msg | 
|  | * @ver: Virtchnl version info | 
|  | * @v_opcode: Opcode for the message | 
|  | * @msg: pointer to the msg buffer | 
|  | * @msglen: msg length | 
|  | * | 
|  | * validate msg format against struct for each opcode | 
|  | */ | 
|  | static inline int | 
|  | virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, | 
|  | u8 *msg, u16 msglen) | 
|  | { | 
|  | bool err_msg_format = false; | 
|  | int valid_len = 0; | 
|  |  | 
|  | /* Validate message length. */ | 
|  | switch (v_opcode) { | 
|  | case VIRTCHNL_OP_VERSION: | 
|  | valid_len = sizeof(struct virtchnl_version_info); | 
|  | break; | 
|  | case VIRTCHNL_OP_RESET_VF: | 
|  | break; | 
|  | case VIRTCHNL_OP_GET_VF_RESOURCES: | 
|  | if (VF_IS_V11(ver)) | 
|  | valid_len = sizeof(u32); | 
|  | break; | 
|  | case VIRTCHNL_OP_CONFIG_TX_QUEUE: | 
|  | valid_len = sizeof(struct virtchnl_txq_info); | 
|  | break; | 
|  | case VIRTCHNL_OP_CONFIG_RX_QUEUE: | 
|  | valid_len = sizeof(struct virtchnl_rxq_info); | 
|  | break; | 
|  | case VIRTCHNL_OP_CONFIG_VSI_QUEUES: | 
|  | valid_len = sizeof(struct virtchnl_vsi_queue_config_info); | 
|  | if (msglen >= valid_len) { | 
|  | struct virtchnl_vsi_queue_config_info *vqc = | 
|  | (struct virtchnl_vsi_queue_config_info *)msg; | 
|  | valid_len += (vqc->num_queue_pairs * | 
|  | sizeof(struct | 
|  | virtchnl_queue_pair_info)); | 
|  | if (vqc->num_queue_pairs == 0) | 
|  | err_msg_format = true; | 
|  | } | 
|  | break; | 
|  | case VIRTCHNL_OP_CONFIG_IRQ_MAP: | 
|  | valid_len = sizeof(struct virtchnl_irq_map_info); | 
|  | if (msglen >= valid_len) { | 
|  | struct virtchnl_irq_map_info *vimi = | 
|  | (struct virtchnl_irq_map_info *)msg; | 
|  | valid_len += (vimi->num_vectors * | 
|  | sizeof(struct virtchnl_vector_map)); | 
|  | if (vimi->num_vectors == 0) | 
|  | err_msg_format = true; | 
|  | } | 
|  | break; | 
|  | case VIRTCHNL_OP_ENABLE_QUEUES: | 
|  | case VIRTCHNL_OP_DISABLE_QUEUES: | 
|  | valid_len = sizeof(struct virtchnl_queue_select); | 
|  | break; | 
|  | case VIRTCHNL_OP_ADD_ETH_ADDR: | 
|  | case VIRTCHNL_OP_DEL_ETH_ADDR: | 
|  | valid_len = sizeof(struct virtchnl_ether_addr_list); | 
|  | if (msglen >= valid_len) { | 
|  | struct virtchnl_ether_addr_list *veal = | 
|  | (struct virtchnl_ether_addr_list *)msg; | 
|  | valid_len += veal->num_elements * | 
|  | sizeof(struct virtchnl_ether_addr); | 
|  | if (veal->num_elements == 0) | 
|  | err_msg_format = true; | 
|  | } | 
|  | break; | 
|  | case VIRTCHNL_OP_ADD_VLAN: | 
|  | case VIRTCHNL_OP_DEL_VLAN: | 
|  | valid_len = sizeof(struct virtchnl_vlan_filter_list); | 
|  | if (msglen >= valid_len) { | 
|  | struct virtchnl_vlan_filter_list *vfl = | 
|  | (struct virtchnl_vlan_filter_list *)msg; | 
|  | valid_len += vfl->num_elements * sizeof(u16); | 
|  | if (vfl->num_elements == 0) | 
|  | err_msg_format = true; | 
|  | } | 
|  | break; | 
|  | case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: | 
|  | valid_len = sizeof(struct virtchnl_promisc_info); | 
|  | break; | 
|  | case VIRTCHNL_OP_GET_STATS: | 
|  | valid_len = sizeof(struct virtchnl_queue_select); | 
|  | break; | 
|  | case VIRTCHNL_OP_IWARP: | 
|  | /* These messages are opaque to us and will be validated in | 
|  | * the RDMA client code. We just need to check for nonzero | 
|  | * length. The firmware will enforce max length restrictions. | 
|  | */ | 
|  | if (msglen) | 
|  | valid_len = msglen; | 
|  | else | 
|  | err_msg_format = true; | 
|  | break; | 
|  | case VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP: | 
|  | break; | 
|  | case VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP: | 
|  | valid_len = sizeof(struct virtchnl_iwarp_qvlist_info); | 
|  | if (msglen >= valid_len) { | 
|  | struct virtchnl_iwarp_qvlist_info *qv = | 
|  | (struct virtchnl_iwarp_qvlist_info *)msg; | 
|  | if (qv->num_vectors == 0) { | 
|  | err_msg_format = true; | 
|  | break; | 
|  | } | 
|  | valid_len += ((qv->num_vectors - 1) * | 
|  | sizeof(struct virtchnl_iwarp_qv_info)); | 
|  | } | 
|  | break; | 
|  | case VIRTCHNL_OP_CONFIG_RSS_KEY: | 
|  | valid_len = sizeof(struct virtchnl_rss_key); | 
|  | if (msglen >= valid_len) { | 
|  | struct virtchnl_rss_key *vrk = | 
|  | (struct virtchnl_rss_key *)msg; | 
|  | valid_len += vrk->key_len - 1; | 
|  | } | 
|  | break; | 
|  | case VIRTCHNL_OP_CONFIG_RSS_LUT: | 
|  | valid_len = sizeof(struct virtchnl_rss_lut); | 
|  | if (msglen >= valid_len) { | 
|  | struct virtchnl_rss_lut *vrl = | 
|  | (struct virtchnl_rss_lut *)msg; | 
|  | valid_len += vrl->lut_entries - 1; | 
|  | } | 
|  | break; | 
|  | case VIRTCHNL_OP_GET_RSS_HENA_CAPS: | 
|  | break; | 
|  | case VIRTCHNL_OP_SET_RSS_HENA: | 
|  | valid_len = sizeof(struct virtchnl_rss_hena); | 
|  | break; | 
|  | case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING: | 
|  | case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING: | 
|  | break; | 
|  | case VIRTCHNL_OP_REQUEST_QUEUES: | 
|  | valid_len = sizeof(struct virtchnl_vf_res_request); | 
|  | break; | 
|  | case VIRTCHNL_OP_ENABLE_CHANNELS: | 
|  | valid_len = sizeof(struct virtchnl_tc_info); | 
|  | if (msglen >= valid_len) { | 
|  | struct virtchnl_tc_info *vti = | 
|  | (struct virtchnl_tc_info *)msg; | 
|  | valid_len += (vti->num_tc - 1) * | 
|  | sizeof(struct virtchnl_channel_info); | 
|  | if (vti->num_tc == 0) | 
|  | err_msg_format = true; | 
|  | } | 
|  | break; | 
|  | case VIRTCHNL_OP_DISABLE_CHANNELS: | 
|  | break; | 
|  | case VIRTCHNL_OP_ADD_CLOUD_FILTER: | 
|  | valid_len = sizeof(struct virtchnl_filter); | 
|  | break; | 
|  | case VIRTCHNL_OP_DEL_CLOUD_FILTER: | 
|  | valid_len = sizeof(struct virtchnl_filter); | 
|  | break; | 
|  | /* These are always errors coming from the VF. */ | 
|  | case VIRTCHNL_OP_EVENT: | 
|  | case VIRTCHNL_OP_UNKNOWN: | 
|  | default: | 
|  | return VIRTCHNL_STATUS_ERR_PARAM; | 
|  | } | 
|  | /* few more checks */ | 
|  | if (err_msg_format || valid_len != msglen) | 
|  | return VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | #endif /* _VIRTCHNL_H_ */ |