spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
        ret = vmbus_post_msg(open_msg,
-                              sizeof(struct vmbus_channel_open_channel));
+                            sizeof(struct vmbus_channel_open_channel), true);
 
        if (ret != 0) {
                err = ret;
        conn_msg.guest_endpoint_id = *shv_guest_servie_id;
        conn_msg.host_service_id = *shv_host_servie_id;
 
-       return vmbus_post_msg(&conn_msg, sizeof(conn_msg));
+       return vmbus_post_msg(&conn_msg, sizeof(conn_msg), true);
 }
 EXPORT_SYMBOL_GPL(vmbus_send_tl_connect_request);
 
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
        ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
-                              sizeof(*msginfo));
+                            sizeof(*msginfo), true);
        if (ret != 0)
                goto cleanup;
 
                gpadl_body->gpadl = next_gpadl_handle;
 
                ret = vmbus_post_msg(gpadl_body,
-                                    submsginfo->msgsize -
-                                    sizeof(*submsginfo));
+                                    submsginfo->msgsize - sizeof(*submsginfo),
+                                    true);
                if (ret != 0)
                        goto cleanup;
 
        list_add_tail(&info->msglistentry,
                      &vmbus_connection.chn_msg_list);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
-       ret = vmbus_post_msg(msg,
-                              sizeof(struct vmbus_channel_gpadl_teardown));
+       ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown),
+                            true);
 
        if (ret)
                goto post_msg_err;
        msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
        msg->child_relid = channel->offermsg.child_relid;
 
-       ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
+       ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel),
+                            true);
 
        if (ret) {
                pr_err("Close failed: close post msg return is %d\n", ret);
 
        memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
        msg.child_relid = relid;
        msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
-       vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released));
+       vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released),
+                      true);
 }
 
 void hv_event_tasklet_disable(struct vmbus_channel *channel)
        init_completion(&vmbus_connection.unload_event);
        memset(&hdr, 0, sizeof(struct vmbus_channel_message_header));
        hdr.msgtype = CHANNELMSG_UNLOAD;
-       vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header));
+       vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header),
+                      !crash);
 
        /*
         * vmbus_initiate_unload() is also called on crash and the crash can be
        msg->msgtype = CHANNELMSG_REQUESTOFFERS;
 
 
-       ret = vmbus_post_msg(msg,
-                              sizeof(struct vmbus_channel_message_header));
+       ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_message_header),
+                            true);
        if (ret != 0) {
                pr_err("Unable to request offers - %d\n", ret);
 
 
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
        ret = vmbus_post_msg(msg,
-                              sizeof(struct vmbus_channel_initiate_contact));
+                            sizeof(struct vmbus_channel_initiate_contact),
+                            true);
        if (ret != 0) {
                spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
                list_del(&msginfo->msglistentry);
 /*
  * vmbus_post_msg - Send a msg on the vmbus's message connection
  */
-int vmbus_post_msg(void *buffer, size_t buflen)
+int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep)
 {
        union hv_connection_id conn_id;
        int ret = 0;
         * insufficient resources. Retry the operation a couple of
         * times before giving up.
         */
-       while (retries < 20) {
+       while (retries < 100) {
                ret = hv_post_message(conn_id, 1, buffer, buflen);
 
                switch (ret) {
                }
 
                retries++;
-               udelay(usec);
-               if (usec < 2048)
+               if (can_sleep && usec > 1000)
+                       msleep(usec / 1000);
+               else if (usec < MAX_UDELAY_MS * 1000)
+                       udelay(usec);
+               else
+                       mdelay(usec / 1000);
+
+               if (usec < 256000)
                        usec *= 2;
        }
        return ret;
 
 int vmbus_connect(void);
 void vmbus_disconnect(void);
 
-int vmbus_post_msg(void *buffer, size_t buflen);
+int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep);
 
 void vmbus_on_event(unsigned long data);
 void vmbus_on_msg_dpc(unsigned long data);