/*
*
* 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, see <http://www.gnu.org/licenses/>.
*
* 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>
/* RSS related */
#define OID_GEN_RECEIVE_SCALE_CAPABILITIES 0x00010203 /* query only */
#define OID_GEN_RECEIVE_SCALE_PARAMETERS 0x00010204 /* query and set */
#define NDIS_OBJECT_TYPE_RSS_CAPABILITIES 0x88
#define NDIS_OBJECT_TYPE_RSS_PARAMETERS 0x89
#define NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2 2
#define NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2 2
struct ndis_obj_header {
u8 type;
u8 rev;
u16 size;
} __packed;
/* ndis_recv_scale_cap/cap_flag */
#define NDIS_RSS_CAPS_MESSAGE_SIGNALED_INTERRUPTS 0x01000000
#define NDIS_RSS_CAPS_CLASSIFICATION_AT_ISR 0x02000000
#define NDIS_RSS_CAPS_CLASSIFICATION_AT_DPC 0x04000000
#define NDIS_RSS_CAPS_USING_MSI_X 0x08000000
#define NDIS_RSS_CAPS_RSS_AVAILABLE_ON_PORTS 0x10000000
#define NDIS_RSS_CAPS_SUPPORTS_MSI_X 0x20000000
#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV4 0x00000100
#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6 0x00000200
#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6_EX 0x00000400
struct ndis_recv_scale_cap { /* NDIS_RECEIVE_SCALE_CAPABILITIES */
struct ndis_obj_header hdr;
u32 cap_flag;
u32 num_int_msg;
u32 num_recv_que;
u16 num_indirect_tabent;
} __packed;
/* ndis_recv_scale_param flags */
#define NDIS_RSS_PARAM_FLAG_BASE_CPU_UNCHANGED 0x0001
#define NDIS_RSS_PARAM_FLAG_HASH_INFO_UNCHANGED 0x0002
#define NDIS_RSS_PARAM_FLAG_ITABLE_UNCHANGED 0x0004
#define NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED 0x0008
#define NDIS_RSS_PARAM_FLAG_DISABLE_RSS 0x0010
/* Hash info bits */
#define NDIS_HASH_FUNC_TOEPLITZ 0x00000001
#define NDIS_HASH_IPV4 0x00000100
#define NDIS_HASH_TCP_IPV4 0x00000200
#define NDIS_HASH_IPV6 0x00000400
#define NDIS_HASH_IPV6_EX 0x00000800
#define NDIS_HASH_TCP_IPV6 0x00001000
#define NDIS_HASH_TCP_IPV6_EX 0x00002000
#define NDIS_RSS_INDIRECTION_TABLE_MAX_SIZE_REVISION_2 (128 * 4)
#define NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 40
#define ITAB_NUM 128
#define HASH_KEYLEN NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2
extern u8 netvsc_hash_key[];
struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */
struct ndis_obj_header hdr;
/* Qualifies the rest of the information */
u16 flag;
/* The base CPU number to do receive processing. not used */
u16 base_cpu_number;
/* This describes the hash function and type being enabled */
u32 hashinfo;
/* The size of indirection table array */
u16 indirect_tabsize;
/* The offset of the indirection table from the beginning of this
* structure
*/
u32 indirect_taboffset;
/* The size of the hash secret key */
u16 hashkey_size;
/* The offset of the secret key from the beginning of this structure */
u32 kashkey_offset;
u32 processor_masks_offset;
u32 num_processor_masks;
u32 processor_masks_entry_size;
};
/* Fwd declaration */
struct ndis_tcp_ip_checksum_info;
/*
* Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
* within the RNDIS
*/
struct hv_netvsc_packet {
/* Bookkeeping stuff */
u32 status;
bool is_data_pkt;
bool xmit_more; /* from skb */
bool cp_partial; /* partial copy into send buffer */
u16 vlan_tci;
u16 q_idx;
struct vmbus_channel *channel;
u64 send_completion_tid;
void *send_completion_ctx;
void (*send_completion)(void *context);
u32 send_buf_index;
/* This points to the memory after page_buf */
struct rndis_message *rndis_msg;
u32 rmsg_size; /* RNDIS header and PPI size */
u32 rmsg_pgcnt; /* page count of RNDIS header and PPI */
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;
};
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;
bool link_change;
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,
struct rndis_message *resp);
void netvsc_xmit_completion(void *context);
int netvsc_recv_callback(struct hv_device *device_obj,
struct hv_netvsc_packet *