Staging: hv: vmbus: Retry vmbus_post_msg() before giving up
authorK. Y. Srinivasan <kys@microsoft.com>
Thu, 25 Aug 2011 16:49:01 +0000 (09:49 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 25 Aug 2011 22:23:19 +0000 (15:23 -0700)
The function hv_post_msg() can fail because of transient resource
conditions. It may be useful to retry the operation.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
arch/x86/include/asm/hyperv.h
drivers/staging/hv/connection.c

index 5df477ac3af7cd9b962241e883a17bd201aec81e..b80420bcd09d822546047174ff073499e187dbeb 100644 (file)
 #define HV_STATUS_INVALID_HYPERCALL_CODE       2
 #define HV_STATUS_INVALID_HYPERCALL_INPUT      3
 #define HV_STATUS_INVALID_ALIGNMENT            4
+#define HV_STATUS_INSUFFICIENT_BUFFERS         19
 
 #endif
index 0e7efce31282dd1e136ef2ef262a2d9061c86be3..a88ad7072566780e9eae11b250bd1c47733fe66e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
@@ -268,10 +269,25 @@ void vmbus_on_event(unsigned long data)
 int vmbus_post_msg(void *buffer, size_t buflen)
 {
        union hv_connection_id conn_id;
+       int ret = 0;
+       int retries = 0;
 
        conn_id.asu32 = 0;
        conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
-       return hv_post_message(conn_id, 1, buffer, buflen);
+
+       /*
+        * hv_post_message() can have transient failures because of
+        * insufficient resources. Retry the operation a couple of
+        * times before giving up.
+        */
+       while (retries < 3) {
+               ret =  hv_post_message(conn_id, 1, buffer, buflen);
+               if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
+                       return ret;
+               retries++;
+               msleep(100);
+       }
+       return ret;
 }
 
 /*