diff options
author | Haiyang Zhang <haiyangz@microsoft.com> | 2014-02-19 18:49:45 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-19 19:52:45 -0500 |
commit | a1eabb0178bcef8eee6286bc646b66e23f4f77ea (patch) | |
tree | 68503c7c3732ce6b697fec768182ad5d2bdc6c57 | |
parent | 86c1a045640d3f34ca1ab2f3e8b102670d21f93a (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.h | 53 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc.c | 25 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 2 |
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 | ||
143 | enum { | 145 | enum { |
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 | ||
198 | enum { | 217 | enum { |
@@ -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 | ||
469 | enum nvsp_subchannel_operation { | ||
470 | NVSP_SUBCHANNEL_NONE = 0, | ||
471 | NVSP_SUBCHANNEL_ALLOCATE, | ||
472 | NVSP_SUBCHANNEL_MAX | ||
473 | }; | ||
474 | |||
475 | struct nvsp_5_subchannel_request { | ||
476 | u32 op; | ||
477 | u32 num_subchannels; | ||
478 | } __packed; | ||
479 | |||
480 | struct nvsp_5_subchannel_complete { | ||
481 | u32 status; | ||
482 | u32 num_subchannels; /* Actual number of subchannels allocated */ | ||
483 | } __packed; | ||
484 | |||
485 | struct 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 | |||
496 | union 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 | |||
450 | union nvsp_all_messages { | 502 | union 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) |