summaryrefslogtreecommitdiffstats
path: root/drivers/hv/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv/connection.c')
-rw-r--r--drivers/hv/connection.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 72855182b191..ced041899456 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -63,6 +63,9 @@ static __u32 vmbus_get_next_version(__u32 current_version)
63 case (VERSION_WIN10): 63 case (VERSION_WIN10):
64 return VERSION_WIN8_1; 64 return VERSION_WIN8_1;
65 65
66 case (VERSION_WIN10_V5):
67 return VERSION_WIN10;
68
66 case (VERSION_WS2008): 69 case (VERSION_WS2008):
67 default: 70 default:
68 return VERSION_INVAL; 71 return VERSION_INVAL;
@@ -80,9 +83,29 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
80 83
81 msg = (struct vmbus_channel_initiate_contact *)msginfo->msg; 84 msg = (struct vmbus_channel_initiate_contact *)msginfo->msg;
82 85
86 memset(msg, 0, sizeof(*msg));
83 msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT; 87 msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
84 msg->vmbus_version_requested = version; 88 msg->vmbus_version_requested = version;
85 msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); 89
90 /*
91 * VMBus protocol 5.0 (VERSION_WIN10_V5) requires that we must use
92 * VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate Contact Message,
93 * and for subsequent messages, we must use the Message Connection ID
94 * field in the host-returned Version Response Message. And, with
95 * VERSION_WIN10_V5, we don't use msg->interrupt_page, but we tell
96 * the host explicitly that we still use VMBUS_MESSAGE_SINT(2) for
97 * compatibility.
98 *
99 * On old hosts, we should always use VMBUS_MESSAGE_CONNECTION_ID (1).
100 */
101 if (version >= VERSION_WIN10_V5) {
102 msg->msg_sint = VMBUS_MESSAGE_SINT;
103 vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID_4;
104 } else {
105 msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
106 vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID;
107 }
108
86 msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]); 109 msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
87 msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]); 110 msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
88 /* 111 /*
@@ -137,6 +160,10 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
137 /* Check if successful */ 160 /* Check if successful */
138 if (msginfo->response.version_response.version_supported) { 161 if (msginfo->response.version_response.version_supported) {
139 vmbus_connection.conn_state = CONNECTED; 162 vmbus_connection.conn_state = CONNECTED;
163
164 if (version >= VERSION_WIN10_V5)
165 vmbus_connection.msg_conn_id =
166 msginfo->response.version_response.msg_conn_id;
140 } else { 167 } else {
141 return -ECONNREFUSED; 168 return -ECONNREFUSED;
142 } 169 }
@@ -354,13 +381,14 @@ void vmbus_on_event(unsigned long data)
354 */ 381 */
355int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep) 382int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep)
356{ 383{
384 struct vmbus_channel_message_header *hdr;
357 union hv_connection_id conn_id; 385 union hv_connection_id conn_id;
358 int ret = 0; 386 int ret = 0;
359 int retries = 0; 387 int retries = 0;
360 u32 usec = 1; 388 u32 usec = 1;
361 389
362 conn_id.asu32 = 0; 390 conn_id.asu32 = 0;
363 conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID; 391 conn_id.u.id = vmbus_connection.msg_conn_id;
364 392
365 /* 393 /*
366 * hv_post_message() can have transient failures because of 394 * hv_post_message() can have transient failures because of
@@ -373,6 +401,18 @@ int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep)
373 switch (ret) { 401 switch (ret) {
374 case HV_STATUS_INVALID_CONNECTION_ID: 402 case HV_STATUS_INVALID_CONNECTION_ID:
375 /* 403 /*
404 * See vmbus_negotiate_version(): VMBus protocol 5.0
405 * requires that we must use
406 * VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate
407 * Contact message, but on old hosts that only
408 * support VMBus protocol 4.0 or lower, here we get
409 * HV_STATUS_INVALID_CONNECTION_ID and we should
410 * return an error immediately without retrying.
411 */
412 hdr = buffer;
413 if (hdr->msgtype == CHANNELMSG_INITIATE_CONTACT)
414 return -EINVAL;
415 /*
376 * We could get this if we send messages too 416 * We could get this if we send messages too
377 * frequently. 417 * frequently.
378 */ 418 */