/* * * Copyright (c) 2011, Microsoft Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. * * Authors: * Haiyang Zhang <haiyangz@microsoft.com> * Hank Janssen <hjanssen@microsoft.com> * K. Y. Srinivasan <kys@microsoft.com> * */ #ifndef _HYPERV_NET_H#define _HYPERV_NET_H #include <linux/list.h>#include <linux/hyperv.h>#include <linux/rndis.h> /* Fwd declaration */struct hv_netvsc_packet; /* Represent the xfer page packet which contains 1 or more netvsc packet */struct xferpage_packet { struct list_head list_ent; u32 status; /* # of netvsc packets this xfer packet contains */ u32 count;}; /* * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame * within the RNDIS */struct hv_netvsc_packet { /* Bookkeeping stuff */ struct list_head list_ent; u32 status; struct hv_device *device; bool is_data_pkt; u16 vlan_tci; /* * Valid only for receives when we break a xfer page packet * into multiple netvsc packets */ struct xferpage_packet *xfer_page_pkt; union { struct { u64 recv_completion_tid; void *recv_completion_ctx; void (*recv_completion)(void *context); } recv; struct { u64 send_completion_tid; void *send_completion_ctx; void (*send_completion)(void *context); } send; } completion; /* This points to the memory after page_buf */ void *extension; u32 total_data_buflen; /* Points to the send/receive buffer where the ethernet frame is */ void *data; u32 page_buf_cnt; struct hv_page_buffer page_buf[0];}; struct netvsc_device_info { unsigned char mac_adr[ETH_ALEN]; bool link_state; /* 0 - link up, 1 - link down */ int ring_size;}; enum rndis_device_state { RNDIS_DEV_UNINITIALIZED = 0, RNDIS_DEV_INITIALIZING, RNDIS_DEV_INITIALIZED, RNDIS_DEV_DATAINITIALIZED,}; struct rndis_device { struct netvsc_device *net_dev; enum rndis_device_state state; bool link_state; atomic_t new_req_id; spinlock_t request_lock; struct list_head req_list; unsigned char hw_mac_adr[ETH_ALEN];}; /* Interface */int netvsc_device_add(struct hv_device *device, void *additional_info);int netvsc_device_remove(struct hv_device *device);int netvsc_send(struct hv_device *device, struct hv_netvsc_packet *packet);void netvsc_linkstatus_callback(struct hv_device *device_obj, unsigned int status);int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet);int rndis_filter_open(struct hv_device *dev);int rndis_filter_close(struct hv_device *dev);int rndis_filter_device_add(struct hv_device *dev, void *additional_info);void rndis_filter_device_remove(struct hv_device *dev);int rndis_filter_receive(struct hv_device *dev, struct hv_netvsc_packet *pkt); int rndis_filter_send(struct hv_device *dev, struct hv_netvsc_packet *pkt); int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac); #define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF) #define NVSP_PROTOCOL_VERSION_1 2#define NVSP_PROTOCOL_VERSION_2 0x30002 enum { NVSP_MSG_TYPE_NONE = 0, /* Init Messages */ NVSP_MSG_TYPE_INIT = 1, NVSP_MSG_TYPE_INIT_COMPLETE = 2, NVSP_VERSION_MSG_START = 100, /* Version 1 Messages */ NVSP_MSG1_TYPE_SEND_NDIS_VER = NVSP_VERSION_MSG_START, NVSP_MSG1_TYPE_SEND_RECV_BUF, NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE, NVSP_MSG1_TYPE_REVOKE_RECV_BUF, NVSP_MSG1_TYPE_SEND_SEND_BUF, NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE, NVSP_MSG1_TYPE_REVOKE_SEND_BUF, NVSP_MSG1_TYPE_SEND_RNDIS_PKT, NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE, /* Version 2 messages */ NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF, NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF_COMP, NVSP_MSG2_TYPE_REVOKE_CHIMNEY_DELEGATED_BUF, NVSP_MSG2_TYPE_RESUME_CHIMNEY_RX_INDICATION, NVSP_MSG2_TYPE_TERMINATE_CHIMNEY, NVSP_MSG2_TYPE_TERMINATE_CHIMNEY_COMP, NVSP_MSG2_TYPE_INDICATE_CHIMNEY_EVENT, NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT, NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT_COMP, NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ, NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ_COMP, NVSP_MSG2_TYPE_ALLOC_RXBUF, NVSP_MSG2_TYPE_ALLOC_RXBUF_COMP, NVSP_MSG2_TYPE_FREE_RXBUF, NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT, NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT_COMP, NVSP_MSG2_TYPE_SEND_NDIS_CONFIG, NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE, NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,}; enum { NVSP_STAT_NONE = 0, NVSP_STAT_SUCCESS, NVSP_STAT_FAIL, NVSP_STAT_PROTOCOL_TOO_NEW, NVSP_STAT_PROTOCOL_TOO_OLD, NVSP_STAT_INVALID_RNDIS_PKT, NVSP_STAT_BUSY, NVSP_STAT_PROTOCOL_UNSUPPORTED, NVSP_STAT_MAX,}; struct nvsp_message_header { u32 msg_type;}; /* Init Messages */ /* * This message is used by the VSC to initialize the channel after the channels * has been opened. This message should never include anything other then * versioning (i.e. this message will be the same for ever). */struct nvsp_message_init { u32 min_protocol_ver; u32 max_protocol_ver;} __packed; /* * This message is used by the VSP to complete the initialization of the * channel. This message should never include anything other then versioning * (i.e. this message will be the same for ever). */struct nvsp_message_init_complete { u32 negotiated_protocol_ver; u32 max_mdl_chain_len; u32 status;} __packed; union nvsp_message_init_uber { struct nvsp_message_init init; struct nvsp_message_init_complete init_complete;} __packed; /* Version 1 Messages */ /* * This message is used by the VSC to send the NDIS version to the VSP. The VSP * can use this information when handling OIDs sent by the VSC. */struct nvsp_1_message_send_ndis_version { u32 ndis_major_ver; u32 ndis_minor_ver;} __packed; /* * This message is used by the VSC to send a receive buffer to the VSP. The VSP * can then use the receive buffer to send data to the VSC. */struct nvsp_1_message_send_receive_buffer { u32 gpadl_handle; u16 id;} __packed; struct nvsp_1_receive_buffer_section { u32 offset; u32 sub_alloc_size; u32 num_sub_allocs; u32 end_offset;} __packed; /* * This message is used by the VSP to acknowledge a receive buffer send by the * VSC. This message must be sent by the VSP before the VSP uses the receive * buffer. */struct nvsp_1_message_send_receive_buffer_complete { u32 status; u32 num_sections; /* * The receive buffer is split into two parts, a large suballocation * section and a small suballocation section. These sections are then * suballocated by a certain size. */ /* * For example, the following break up of the receive buffer has 6 * large suballocations and 10 small suballocations. */ /* * | Large Section | | Small Section | * ------------------------------------------------------------ * | | | | | | | | | | | | | | | | | | * | | * LargeOffset SmallOffset */ struct nvsp_1_receive_buffer_section sections[1];} __packed; /* * This message is sent by the VSC to revoke the receive buffer. After the VSP * completes this transaction, the vsp should never use the receive buffer * again. */struct nvsp_1_message_revoke_receive_buffer { u16 id;}; /* * This message is used by the VSC to send a send buffer to the VSP. The VSC * can then use the send buffer to send data to the VSP. */struct nvsp_1_message_send_send_buffer { u32 gpadl_handle; u16 id;} __packed; /* * This message is used by the VSP to acknowledge a send buffer sent by the * VSC. This message must be sent by the VSP before the VSP uses the sent * buffer. */struct nvsp_1_message_send_send_buffer_complete { u32 status; /* * The VSC gets to choose the size of the send buffer and the VSP gets * to choose the sections size of the buffer. This was done to enable * dynamic reconfigurations when the cost of GPA-direct buffers * decreases. */ u32 section_size;} __packed; /* * This message is sent by the VSC to revoke the send buffer. After the VSP * completes this transaction, the vsp should never use the send buffer again. */struct nvsp_1_message_revoke_send_buffer { u16 id;}; /* * This message is used by both the VSP and the VSC to send a RNDIS message to * the opposite channel endpoint. */struct nvsp_1_message_send_rndis_packet { /* * This field is specified by RNIDS. They assume there's two different * channels of communication. However, the Network VSP only has one. * Therefore, the channel travels with the RNDIS packet. */ u32 channel_type; /* * This field is used to send part or all of the data through a send * buffer. This values specifies an index into the send buffer. If the * index is 0xFFFFFFFF, then the send buffer is not being used and all * of the data was sent through other VMBus mechanisms. */ u32 send_buf_section_index; u32 send_buf_section_size;} __packed; /* * This message is used by both the VSP and the VSC to complete a RNDIS message * to the opposite channel endpoint. At this point, the initiator of this * message cannot use any resources associated with the original RNDIS packet. */struct nvsp_1_message_send_rndis_packet_complete { u32 status;}; union nvsp_1_message_uber { struct nvsp_1_message_send_ndis_version send_ndis_ver; struct nvsp_1_message_send_receive_buffer send_recv_buf; struct nvsp_1_message_send_receive_buffer_complete send_recv_buf_complete; struct nvsp_1_message_revoke_receive_buffer revoke_recv_buf; struct nvsp_1_message_send_send_buffer send_send_buf; struct nvsp_1_message_send_send_buffer_complete send_send_buf_complete; struct nvsp_1_message_revoke_send_buffer revoke_send_buf; struct nvsp_1_message_send_rndis_packet send_rndis_pkt; struct nvsp_1_message_send_rndis_packet_complete send_rndis_pkt_complete;} __packed; /* * Network VSP protocol version 2 messages: */struct nvsp_2_vsc_capability { union { u64 data; struct { u64 vmq:1; u64 chimney:1; u64 sriov:1; u64 ieee8021q:1; u64 correlation_id:1; }; };} __packed; struct nvsp_2_send_ndis_config { u32 mtu; u32 reserved; struct nvsp_2_vsc_capability capability;} __packed; /* Allocate receive buffer */struct nvsp_2_alloc_rxbuf { /* Allocation ID to match the allocation request and response */ u32 alloc_id; /* Length of the VM shared memory receive buffer that needs to * be allocated */ u32 len;} __packed; /* Allocate receive buffer complete */struct nvsp_2_alloc_rxbuf_comp { /* The NDIS_STATUS code for buffer allocation */ u32 status; u32 alloc_id; /* GPADL handle for the allocated receive buffer */ u32 gpadl_handle; /* Receive buffer ID */ u64 recv_buf_id;} __packed; struct nvsp_2_free_rxbuf { u64 recv_buf_id;} __packed; union nvsp_2_message_uber { struct nvsp_2_send_ndis_config send_ndis_config; struct nvsp_2_alloc_rxbuf alloc_rxbuf; struct nvsp_2_alloc_rxbuf_comp alloc_rxbuf_comp; struct nvsp_2_free_rxbuf free_rxbuf;} __packed; union nvsp_all_messages { union nvsp_message_init_uber init_msg; union nvsp_1_message_uber v1_msg; union nvsp_2_message_uber v2_msg;} __packed; /* ALL Messages */struct nvsp_message { struct nvsp_message_header hdr; union nvsp_all_messages msg;} __packed; #define NETVSC_MTU 65536 #define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*2) /* 2MB */ #define NETVSC_RECEIVE_BUFFER_ID 0xcafe /* Preallocated receive packets */#define NETVSC_RECEIVE_PACKETLIST_COUNT 256 #define NETVSC_PACKET_SIZE 2048 /* Per netvsc channel-specific */struct netvsc_device { struct hv_device *dev; u32 nvsp_version; atomic_t num_outstanding_sends; wait_queue_head_t wait_drain; bool start_remove; bool destroy; /* * List of free preallocated hv_netvsc_packet to represent receive * packet */ struct list_head recv_pkt_list; spinlock_t recv_pkt_list_lock; /* Receive buffer allocated by us but manages by NetVSP */ void *recv_buf; u32 recv_buf_size; u32 recv_buf_gpadl_handle; u32 recv_section_cnt; struct nvsp_1_receive_buffer_section *recv_section; /* Used for NetVSP initialization protocol */ struct completion channel_init_wait;Lines 1–500 of 911. Load more
/* * * Copyright (c) 2011, Microsoft Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. * * Authors: * Haiyang Zhang <haiyangz@microsoft.com> * Hank Janssen <hjanssen@microsoft.com> * K. Y. Srinivasan <kys@microsoft.com> * */ #ifndef _HYPERV_NET_H #define _HYPERV_NET_H #include <linux/list.h> #include <linux/hyperv.h> #include <linux/rndis.h> /* Fwd declaration */ struct hv_netvsc_packet; /* Represent the xfer page packet which contains 1 or more netvsc packet */ struct xferpage_packet { struct list_head list_ent; u32 status; /* # of netvsc packets this xfer packet contains */ u32 count; }; /* * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame * within the RNDIS */ struct hv_netvsc_packet { /* Bookkeeping stuff */ struct list_head list_ent; u32 status; struct hv_device *device; bool is_data_pkt; u16 vlan_tci; /* * Valid only for receives when we break a xfer page packet * into multiple netvsc packets */ struct xferpage_packet *xfer_page_pkt; union { struct { u64 recv_completion_tid; void *recv_completion_ctx; void (*recv_completion)(void *context); } recv; struct { u64 send_completion_tid; void *send_completion_ctx; void (*send_completion)(void *context); } send; } completion; /* This points to the memory after page_buf */ void *extension; u32 total_data_buflen; /* Points to the send/receive buffer where the ethernet frame is */ void *data; u32 page_buf_cnt; struct hv_page_buffer page_buf[0]; }; struct netvsc_device_info { unsigned char mac_adr[ETH_ALEN]; bool link_state; /* 0 - link up, 1 - link down */ int ring_size; }; enum rndis_device_state { RNDIS_DEV_UNINITIALIZED = 0, RNDIS_DEV_INITIALIZING, RNDIS_DEV_INITIALIZED, RNDIS_DEV_DATAINITIALIZED, }; struct rndis_device { struct netvsc_device *net_dev; enum rndis_device_state state; bool link_state; atomic_t new_req_id; spinlock_t request_lock; struct list_head req_list; unsigned char hw_mac_adr[ETH_ALEN]; }; /* Interface */ int netvsc_device_add(struct hv_device *device, void *additional_info); int netvsc_device_remove(struct hv_device *device); int netvsc_send(struct hv_device *device, struct hv_netvsc_packet *packet); void netvsc_linkstatus_callback(struct hv_device *device_obj, unsigned int status); int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet); int rndis_filter_open(struct hv_device *dev); int rndis_filter_close(struct hv_device *dev); int rndis_filter_device_add(struct hv_device *dev, void *additional_info); void rndis_filter_device_remove(struct hv_device *dev); int rndis_filter_receive(struct hv_device *dev, struct hv_netvsc_packet *pkt); int rndis_filter_send(struct hv_device *dev, struct hv_netvsc_packet *pkt); int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter); int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac); #define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF) #define NVSP_PROTOCOL_VERSION_1 2 #define NVSP_PROTOCOL_VERSION_2 0x30002 enum { NVSP_MSG_TYPE_NONE = 0, /* Init Messages */ NVSP_MSG_TYPE_INIT = 1, NVSP_MSG_TYPE_INIT_COMPLETE = 2, NVSP_VERSION_MSG_START = 100, /* Version 1 Messages */ NVSP_MSG1_TYPE_SEND_NDIS_VER = NVSP_VERSION_MSG_START, NVSP_MSG1_TYPE_SEND_RECV_BUF, NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE, NVSP_MSG1_TYPE_REVOKE_RECV_BUF, NVSP_MSG1_TYPE_SEND_SEND_BUF, NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE, NVSP_MSG1_TYPE_REVOKE_SEND_BUF, NVSP_MSG1_TYPE_SEND_RNDIS_PKT, NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE, /* Version 2 messages */ NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF, NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF_COMP, NVSP_MSG2_TYPE_REVOKE_CHIMNEY_DELEGATED_BUF, NVSP_MSG2_TYPE_RESUME_CHIMNEY_RX_INDICATION, NVSP_MSG2_TYPE_TERMINATE_CHIMNEY, NVSP_MSG2_TYPE_TERMINATE_CHIMNEY_COMP, NVSP_MSG2_TYPE_INDICATE_CHIMNEY_EVENT, NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT, NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT_COMP, NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ, NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ_COMP, NVSP_MSG2_TYPE_ALLOC_RXBUF, NVSP_MSG2_TYPE_ALLOC_RXBUF_COMP, NVSP_MSG2_TYPE_FREE_RXBUF, NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT, NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT_COMP, NVSP_MSG2_TYPE_SEND_NDIS_CONFIG, NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE, NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP, }; enum { NVSP_STAT_NONE = 0, NVSP_STAT_SUCCESS, NVSP_STAT_FAIL, NVSP_STAT_PROTOCOL_TOO_NEW, NVSP_STAT_PROTOCOL_TOO_OLD, NVSP_STAT_INVALID_RNDIS_PKT, NVSP_STAT_BUSY, NVSP_STAT_PROTOCOL_UNSUPPORTED, NVSP_STAT_MAX, }; struct nvsp_message_header { u32 msg_type; }; /* Init Messages */ /* * This message is used by the VSC to initialize the channel after the channels * has been opened. This message should never include anything other then * versioning (i.e. this message will be the same for ever). */ struct nvsp_message_init { u32 min_protocol_ver; u32 max_protocol_ver; } __packed; /* * This message is used by the VSP to complete the initialization of the * channel. This message should never include anything other then versioning * (i.e. this message will be the same for ever). */ struct nvsp_message_init_complete { u32 negotiated_protocol_ver; u32 max_mdl_chain_len; u32 status; } __packed; union nvsp_message_init_uber { struct nvsp_message_init init; struct nvsp_message_init_complete init_complete; } __packed; /* Version 1 Messages */ /* * This message is used by the VSC to send the NDIS version to the VSP. The VSP * can use this information when handling OIDs sent by the VSC. */ struct nvsp_1_message_send_ndis_version { u32 ndis_major_ver; u32 ndis_minor_ver; } __packed; /* * This message is used by the VSC to send a receive buffer to the VSP. The VSP * can then use the receive buffer to send data to the VSC. */ struct nvsp_1_message_send_receive_buffer { u32 gpadl_handle; u16 id; } __packed; struct nvsp_1_receive_buffer_section { u32 offset; u32 sub_alloc_size; u32 num_sub_allocs; u32 end_offset; } __packed; /* * This message is used by the VSP to acknowledge a receive buffer send by the * VSC. This message must be sent by the VSP before the VSP uses the receive * buffer. */ struct nvsp_1_message_send_receive_buffer_complete { u32 status; u32 num_sections; /* * The receive buffer is split into two parts, a large suballocation * section and a small suballocation section. These sections are then * suballocated by a certain size. */ /* * For example, the following break up of the receive buffer has 6 * large suballocations and 10 small suballocations. */ /* * | Large Section | | Small Section | * ------------------------------------------------------------ * | | | | | | | | | | | | | | | | | | * | | * LargeOffset SmallOffset */ struct nvsp_1_receive_buffer_section sections[1]; } __packed; /* * This message is sent by the VSC to revoke the receive buffer. After the VSP * completes this transaction, the vsp should never use the receive buffer * again. */ struct nvsp_1_message_revoke_receive_buffer { u16 id; }; /* * This message is used by the VSC to send a send buffer to the VSP. The VSC * can then use the send buffer to send data to the VSP. */ struct nvsp_1_message_send_send_buffer { u32 gpadl_handle; u16 id; } __packed; /* * This message is used by the VSP to acknowledge a send buffer sent by the * VSC. This message must be sent by the VSP before the VSP uses the sent * buffer. */ struct nvsp_1_message_send_send_buffer_complete { u32 status; /* * The VSC gets to choose the size of the send buffer and the VSP gets * to choose the sections size of the buffer. This was done to enable * dynamic reconfigurations when the cost of GPA-direct buffers * decreases. */ u32 section_size; } __packed; /* * This message is sent by the VSC to revoke the send buffer. After the VSP * completes this transaction, the vsp should never use the send buffer again. */ struct nvsp_1_message_revoke_send_buffer { u16 id; }; /* * This message is used by both the VSP and the VSC to send a RNDIS message to * the opposite channel endpoint. */ struct nvsp_1_message_send_rndis_packet { /* * This field is specified by RNIDS. They assume there's two different * channels of communication. However, the Network VSP only has one. * Therefore, the channel travels with the RNDIS packet. */ u32 channel_type; /* * This field is used to send part or all of the data through a send * buffer. This values specifies an index into the send buffer. If the * index is 0xFFFFFFFF, then the send buffer is not being used and all * of the data was sent through other VMBus mechanisms. */ u32 send_buf_section_index; u32 send_buf_section_size; } __packed; /* * This message is used by both the VSP and the VSC to complete a RNDIS message * to the opposite channel endpoint. At this point, the initiator of this * message cannot use any resources associated with the original RNDIS packet. */ struct nvsp_1_message_send_rndis_packet_complete { u32 status; }; union nvsp_1_message_uber { struct nvsp_1_message_send_ndis_version send_ndis_ver; struct nvsp_1_message_send_receive_buffer send_recv_buf; struct nvsp_1_message_send_receive_buffer_complete send_recv_buf_complete; struct nvsp_1_message_revoke_receive_buffer revoke_recv_buf; struct nvsp_1_message_send_send_buffer send_send_buf; struct nvsp_1_message_send_send_buffer_complete send_send_buf_complete; struct nvsp_1_message_revoke_send_buffer revoke_send_buf; struct nvsp_1_message_send_rndis_packet send_rndis_pkt; struct nvsp_1_message_send_rndis_packet_complete send_rndis_pkt_complete; } __packed; /* * Network VSP protocol version 2 messages: */ struct nvsp_2_vsc_capability { union { u64 data; struct { u64 vmq:1; u64 chimney:1; u64 sriov:1; u64 ieee8021q:1; u64 correlation_id:1; }; }; } __packed; struct nvsp_2_send_ndis_config { u32 mtu; u32 reserved; struct nvsp_2_vsc_capability capability; } __packed; /* Allocate receive buffer */ struct nvsp_2_alloc_rxbuf { /* Allocation ID to match the allocation request and response */ u32 alloc_id; /* Length of the VM shared memory receive buffer that needs to * be allocated */ u32 len; } __packed; /* Allocate receive buffer complete */ struct nvsp_2_alloc_rxbuf_comp { /* The NDIS_STATUS code for buffer allocation */ u32 status; u32 alloc_id; /* GPADL handle for the allocated receive buffer */ u32 gpadl_handle; /* Receive buffer ID */ u64 recv_buf_id; } __packed; struct nvsp_2_free_rxbuf { u64 recv_buf_id; } __packed; union nvsp_2_message_uber { struct nvsp_2_send_ndis_config send_ndis_config; struct nvsp_2_alloc_rxbuf alloc_rxbuf; struct nvsp_2_alloc_rxbuf_comp alloc_rxbuf_comp; struct nvsp_2_free_rxbuf free_rxbuf; } __packed; union nvsp_all_messages { union nvsp_message_init_uber init_msg; union nvsp_1_message_uber v1_msg; union nvsp_2_message_uber v2_msg; } __packed; /* ALL Messages */ struct nvsp_message { struct nvsp_message_header hdr; union nvsp_all_messages msg; } __packed; #define NETVSC_MTU 65536 #define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*2) /* 2MB */ #define NETVSC_RECEIVE_BUFFER_ID 0xcafe /* Preallocated receive packets */ #define NETVSC_RECEIVE_PACKETLIST_COUNT 256 #define NETVSC_PACKET_SIZE 2048 /* Per netvsc channel-specific */ struct netvsc_device { struct hv_device *dev; u32 nvsp_version; atomic_t num_outstanding_sends; wait_queue_head_t wait_drain; bool start_remove; bool destroy; /* * List of free preallocated hv_netvsc_packet to represent receive * packet */ struct list_head recv_pkt_list; spinlock_t recv_pkt_list_lock; /* Receive buffer allocated by us but manages by NetVSP */ void *recv_buf; u32 recv_buf_size; u32 recv_buf_gpadl_handle; u32 recv_section_cnt; struct nvsp_1_receive_buffer_section *recv_section; /* Used for NetVSP initialization protocol */ struct completion channel_init_wait;