summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv/vmbus/hv_connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hyperv/vmbus/hv_connection.c')
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c
index aa1e59e..e170298 100644
--- a/sys/dev/hyperv/vmbus/hv_connection.c
+++ b/sys/dev/hyperv/vmbus/hv_connection.c
@@ -364,31 +364,35 @@ hv_vmbus_on_events(int cpu)
/**
* 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;
+ sbintime_t time = SBT_1MS;
+ int retries;
+ int ret;
- /* NetScaler delays from previous code were consolidated here */
- static int delayAmount[] = {100, 100, 100, 500, 500, 5000, 5000, 5000};
+ connId.as_uint32_t = 0;
+ connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
- /* for(each entry in delayAmount) try to post message,
- * delay a little bit before retrying
+ /*
+ * 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);
}
/**
OpenPOWER on IntegriCloud