aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaiyang Zhang <haiyangz@microsoft.com>2014-02-19 18:49:45 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-19 19:52:45 -0500
commita1eabb0178bcef8eee6286bc646b66e23f4f77ea (patch)
tree68503c7c3732ce6b697fec768182ad5d2bdc6c57
parent86c1a045640d3f34ca1ab2f3e8b102670d21f93a (diff)
hyperv: Add latest NetVSP versions to auto negotiation
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>
-rw-r--r--drivers/net/hyperv/hyperv_net.h53
-rw-r--r--drivers/net/hyperv/netvsc.c25
-rw-r--r--drivers/net/hyperv/netvsc_drv.c2
3 files changed, 70 insertions, 10 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 01a16ea77a5a..39fc230f5c20 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -139,6 +139,8 @@ int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);
139 139
140#define NVSP_PROTOCOL_VERSION_1 2 140#define NVSP_PROTOCOL_VERSION_1 2
141#define NVSP_PROTOCOL_VERSION_2 0x30002 141#define NVSP_PROTOCOL_VERSION_2 0x30002
142#define NVSP_PROTOCOL_VERSION_4 0x40000
143#define NVSP_PROTOCOL_VERSION_5 0x50000
142 144
143enum { 145enum {
144 NVSP_MSG_TYPE_NONE = 0, 146 NVSP_MSG_TYPE_NONE = 0,
@@ -193,6 +195,23 @@ enum {
193 195
194 NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE, 196 NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE,
195 NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP, 197 NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,
198
199 NVSP_MSG2_MAX = NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,
200
201 /* Version 4 messages */
202 NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION,
203 NVSP_MSG4_TYPE_SWITCH_DATA_PATH,
204 NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED,
205
206 NVSP_MSG4_MAX = NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED,
207
208 /* Version 5 messages */
209 NVSP_MSG5_TYPE_OID_QUERY_EX,
210 NVSP_MSG5_TYPE_OID_QUERY_EX_COMP,
211 NVSP_MSG5_TYPE_SUBCHANNEL,
212 NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE,
213
214 NVSP_MSG5_MAX = NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE,
196}; 215};
197 216
198enum { 217enum {
@@ -447,10 +466,44 @@ union nvsp_2_message_uber {
447 struct nvsp_2_free_rxbuf free_rxbuf; 466 struct nvsp_2_free_rxbuf free_rxbuf;
448} __packed; 467} __packed;
449 468
469enum nvsp_subchannel_operation {
470 NVSP_SUBCHANNEL_NONE = 0,
471 NVSP_SUBCHANNEL_ALLOCATE,
472 NVSP_SUBCHANNEL_MAX
473};
474
475struct nvsp_5_subchannel_request {
476 u32 op;
477 u32 num_subchannels;
478} __packed;
479
480struct nvsp_5_subchannel_complete {
481 u32 status;
482 u32 num_subchannels; /* Actual number of subchannels allocated */
483} __packed;
484
485struct nvsp_5_send_indirect_table {
486 /* The number of entries in the send indirection table */
487 u32 count;
488
489 /* The offset of the send indireciton table from top of this struct.
490 * The send indirection table tells which channel to put the send
491 * traffic on. Each entry is a channel number.
492 */
493 u32 offset;
494} __packed;
495
496union nvsp_5_message_uber {
497 struct nvsp_5_subchannel_request subchn_req;
498 struct nvsp_5_subchannel_complete subchn_comp;
499 struct nvsp_5_send_indirect_table send_table;
500} __packed;
501
450union nvsp_all_messages { 502union nvsp_all_messages {
451 union nvsp_message_init_uber init_msg; 503 union nvsp_message_init_uber init_msg;
452 union nvsp_1_message_uber v1_msg; 504 union nvsp_1_message_uber v1_msg;
453 union nvsp_2_message_uber v2_msg; 505 union nvsp_2_message_uber v2_msg;
506 union nvsp_5_message_uber v5_msg;
454} __packed; 507} __packed;
455 508
456/* ALL Messages */ 509/* ALL Messages */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 9a0e9c6f1414..1a0280dcba7e 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -290,7 +290,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
290 NVSP_STAT_SUCCESS) 290 NVSP_STAT_SUCCESS)
291 return -EINVAL; 291 return -EINVAL;
292 292
293 if (nvsp_ver != NVSP_PROTOCOL_VERSION_2) 293 if (nvsp_ver == NVSP_PROTOCOL_VERSION_1)
294 return 0; 294 return 0;
295 295
296 /* NVSPv2 only: Send NDIS config */ 296 /* NVSPv2 only: Send NDIS config */
@@ -314,6 +314,9 @@ static int netvsc_connect_vsp(struct hv_device *device)
314 struct nvsp_message *init_packet; 314 struct nvsp_message *init_packet;
315 int ndis_version; 315 int ndis_version;
316 struct net_device *ndev; 316 struct net_device *ndev;
317 u32 ver_list[] = { NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2,
318 NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5 };
319 int i, num_ver = 4; /* number of different NVSP versions */
317 320
318 net_device = get_outbound_net_device(device); 321 net_device = get_outbound_net_device(device);
319 if (!net_device) 322 if (!net_device)
@@ -323,13 +326,14 @@ static int netvsc_connect_vsp(struct hv_device *device)
323 init_packet = &net_device->channel_init_pkt; 326 init_packet = &net_device->channel_init_pkt;
324 327
325 /* Negotiate the latest NVSP protocol supported */ 328 /* Negotiate the latest NVSP protocol supported */
326 if (negotiate_nvsp_ver(device, net_device, init_packet, 329 for (i = num_ver - 1; i >= 0; i--)
327 NVSP_PROTOCOL_VERSION_2) == 0) { 330 if (negotiate_nvsp_ver(device, net_device, init_packet,
328 net_device->nvsp_version = NVSP_PROTOCOL_VERSION_2; 331 ver_list[i]) == 0) {
329 } else if (negotiate_nvsp_ver(device, net_device, init_packet, 332 net_device->nvsp_version = ver_list[i];
330 NVSP_PROTOCOL_VERSION_1) == 0) { 333 break;
331 net_device->nvsp_version = NVSP_PROTOCOL_VERSION_1; 334 }
332 } else { 335
336 if (i < 0) {
333 ret = -EPROTO; 337 ret = -EPROTO;
334 goto cleanup; 338 goto cleanup;
335 } 339 }
@@ -339,7 +343,10 @@ static int netvsc_connect_vsp(struct hv_device *device)
339 /* Send the ndis version */ 343 /* Send the ndis version */
340 memset(init_packet, 0, sizeof(struct nvsp_message)); 344 memset(init_packet, 0, sizeof(struct nvsp_message));
341 345
342 ndis_version = 0x00050001; 346 if (net_device->nvsp_version <= NVSP_PROTOCOL_VERSION_4)
347 ndis_version = 0x00050001;
348 else
349 ndis_version = 0x0006001e;
343 350
344 init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER; 351 init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER;
345 init_packet->msg.v1_msg. 352 init_packet->msg.v1_msg.
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index bcd2df2f406a..9ef6be90a81c 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -327,7 +327,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
327 if (nvdev == NULL || nvdev->destroy) 327 if (nvdev == NULL || nvdev->destroy)
328 return -ENODEV; 328 return -ENODEV;
329 329
330 if (nvdev->nvsp_version == NVSP_PROTOCOL_VERSION_2) 330 if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
331 limit = NETVSC_MTU; 331 limit = NETVSC_MTU;
332 332
333 if (mtu < 68 || mtu > limit) 333 if (mtu < 68 || mtu > limit)