hyperv: Add latest NetVSP versions to auto negotiation
authorHaiyang Zhang <haiyangz@microsoft.com>
Wed, 19 Feb 2014 23:49:45 +0000 (15:49 -0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 20 Feb 2014 00:52:45 +0000 (19:52 -0500)
It auto negotiates the highest NetVSP version supported by both guest and host.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c

index 01a16ea..39fc230 100644 (file)
@@ -139,6 +139,8 @@ int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);
 
 #define NVSP_PROTOCOL_VERSION_1                2
 #define NVSP_PROTOCOL_VERSION_2                0x30002
+#define NVSP_PROTOCOL_VERSION_4                0x40000
+#define NVSP_PROTOCOL_VERSION_5                0x50000
 
 enum {
        NVSP_MSG_TYPE_NONE = 0,
@@ -193,6 +195,23 @@ enum {
 
        NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE,
        NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,
+
+       NVSP_MSG2_MAX = NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,
+
+       /* Version 4 messages */
+       NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION,
+       NVSP_MSG4_TYPE_SWITCH_DATA_PATH,
+       NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED,
+
+       NVSP_MSG4_MAX = NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED,
+
+       /* Version 5 messages */
+       NVSP_MSG5_TYPE_OID_QUERY_EX,
+       NVSP_MSG5_TYPE_OID_QUERY_EX_COMP,
+       NVSP_MSG5_TYPE_SUBCHANNEL,
+       NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE,
+
+       NVSP_MSG5_MAX = NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE,
 };
 
 enum {
@@ -447,10 +466,44 @@ union nvsp_2_message_uber {
        struct nvsp_2_free_rxbuf free_rxbuf;
 } __packed;
 
+enum nvsp_subchannel_operation {
+       NVSP_SUBCHANNEL_NONE = 0,
+       NVSP_SUBCHANNEL_ALLOCATE,
+       NVSP_SUBCHANNEL_MAX
+};
+
+struct nvsp_5_subchannel_request {
+       u32 op;
+       u32 num_subchannels;
+} __packed;
+
+struct nvsp_5_subchannel_complete {
+       u32 status;
+       u32 num_subchannels; /* Actual number of subchannels allocated */
+} __packed;
+
+struct nvsp_5_send_indirect_table {
+       /* The number of entries in the send indirection table */
+       u32 count;
+
+       /* The offset of the send indireciton table from top of this struct.
+        * The send indirection table tells which channel to put the send
+        * traffic on. Each entry is a channel number.
+        */
+       u32 offset;
+} __packed;
+
+union nvsp_5_message_uber {
+       struct nvsp_5_subchannel_request subchn_req;
+       struct nvsp_5_subchannel_complete subchn_comp;
+       struct nvsp_5_send_indirect_table send_table;
+} __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;
+       union nvsp_5_message_uber v5_msg;
 } __packed;
 
 /* ALL Messages */
index 9a0e9c6..1a0280d 100644 (file)
@@ -290,7 +290,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
            NVSP_STAT_SUCCESS)
                return -EINVAL;
 
-       if (nvsp_ver != NVSP_PROTOCOL_VERSION_2)
+       if (nvsp_ver == NVSP_PROTOCOL_VERSION_1)
                return 0;
 
        /* NVSPv2 only: Send NDIS config */
@@ -314,6 +314,9 @@ static int netvsc_connect_vsp(struct hv_device *device)
        struct nvsp_message *init_packet;
        int ndis_version;
        struct net_device *ndev;
+       u32 ver_list[] = { NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2,
+               NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5 };
+       int i, num_ver = 4; /* number of different NVSP versions */
 
        net_device = get_outbound_net_device(device);
        if (!net_device)
@@ -323,13 +326,14 @@ static int netvsc_connect_vsp(struct hv_device *device)
        init_packet = &net_device->channel_init_pkt;
 
        /* Negotiate the latest NVSP protocol supported */
-       if (negotiate_nvsp_ver(device, net_device, init_packet,
-                              NVSP_PROTOCOL_VERSION_2) == 0) {
-               net_device->nvsp_version = NVSP_PROTOCOL_VERSION_2;
-       } else if (negotiate_nvsp_ver(device, net_device, init_packet,
-                                   NVSP_PROTOCOL_VERSION_1) == 0) {
-               net_device->nvsp_version = NVSP_PROTOCOL_VERSION_1;
-       } else {
+       for (i = num_ver - 1; i >= 0; i--)
+               if (negotiate_nvsp_ver(device, net_device, init_packet,
+                                      ver_list[i])  == 0) {
+                       net_device->nvsp_version = ver_list[i];
+                       break;
+               }
+
+       if (i < 0) {
                ret = -EPROTO;
                goto cleanup;
        }
@@ -339,7 +343,10 @@ static int netvsc_connect_vsp(struct hv_device *device)
        /* Send the ndis version */
        memset(init_packet, 0, sizeof(struct nvsp_message));
 
-       ndis_version = 0x00050001;
+       if (net_device->nvsp_version <= NVSP_PROTOCOL_VERSION_4)
+               ndis_version = 0x00050001;
+       else
+               ndis_version = 0x0006001e;
 
        init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER;
        init_packet->msg.v1_msg.
index bcd2df2..9ef6be9 100644 (file)
@@ -327,7 +327,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
        if (nvdev == NULL || nvdev->destroy)
                return -ENODEV;
 
-       if (nvdev->nvsp_version == NVSP_PROTOCOL_VERSION_2)
+       if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
                limit = NETVSC_MTU;
 
        if (mtu < 68 || mtu > limit)