aboutsummaryrefslogtreecommitdiff
path: root/website/static/security/patches/EN-16:15/vmbus.patch
blob: 1fb7b0d14abe44bab7eeccd0db17787d3013248d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
--- sys/dev/hyperv/vmbus/hv_connection.c.orig
+++ sys/dev/hyperv/vmbus/hv_connection.c
@@ -476,31 +476,35 @@
 /**
  * Send a msg on the vmbus's message connection
  */
-int hv_vmbus_post_message(void *buffer, size_t bufferLen) {
-	int ret = 0;
+int hv_vmbus_post_message(void *buffer, size_t bufferLen)
+{
 	hv_vmbus_connection_id connId;
-	unsigned retries = 0;
-
-	/* NetScaler delays from previous code were consolidated here */
-	static int delayAmount[] = {100, 100, 100, 500, 500, 5000, 5000, 5000};
-
-	/* for(each entry in delayAmount) try to post message,
-	 *  delay a little bit before retrying
+	sbintime_t time = SBT_1MS;
+	int retries;
+	int ret;
+
+	connId.as_uint32_t = 0;
+	connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
+
+	/*
+	 * We retry to cope with transient failures caused by host side's
+	 * insufficient resources. 20 times should suffice in practice.
 	 */
-	for (retries = 0;
-	    retries < sizeof(delayAmount)/sizeof(delayAmount[0]); retries++) {
-	    connId.as_uint32_t = 0;
-	    connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
-	    ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer, bufferLen);
-	    if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
-		break;
-	    /* TODO: KYS We should use a blocking wait call */
-	    DELAY(delayAmount[retries]);
+	for (retries = 0; retries < 20; retries++) {
+		ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer,
+						    bufferLen);
+		if (ret == HV_STATUS_SUCCESS)
+			return (0);
+
+		pause_sbt("pstmsg", time, 0, C_HARDCLOCK);
+		if (time < SBT_1S * 2)
+			time *= 2;
 	}
 
-	KASSERT(ret == 0, ("Error VMBUS: Message Post Failed\n"));
+	KASSERT(ret == HV_STATUS_SUCCESS,
+		("Error VMBUS: Message Post Failed, ret=%d\n", ret));
 
-	return (ret);
+	return (EAGAIN);
 }
 
 /**
--- sys/dev/hyperv/vmbus/hv_vmbus_priv.h.orig
+++ sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -70,6 +70,7 @@
  *    You did not supply enough message buffers to send a message.
  */
 
+#define HV_STATUS_SUCCESS                ((uint16_t)0)
 #define HV_STATUS_INSUFFICIENT_BUFFERS   ((uint16_t)0x0013)
 
 typedef void (*hv_vmbus_channel_callback)(void *context);