summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c41
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c10
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h3
3 files changed, 49 insertions, 5 deletions
diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
index 9d24dd7..5d8df94 100644
--- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
+++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
@@ -30,7 +30,10 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/mbuf.h>
+#include <sys/mutex.h>
#include "hv_vmbus_priv.h"
@@ -95,6 +98,14 @@ typedef struct hv_work_item {
void* context;
} hv_work_item;
+static struct mtx vmbus_chwait_lock;
+MTX_SYSINIT(vmbus_chwait_lk, &vmbus_chwait_lock, "vmbus primarych wait lock",
+ MTX_DEF);
+static uint32_t vmbus_chancnt;
+static uint32_t vmbus_devcnt;
+
+#define VMBUS_CHANCNT_DONE 0x80000000
+
/**
* Implementation of the work abstraction.
*/
@@ -279,6 +290,11 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
mtx_unlock(&hv_vmbus_g_connection.channel_lock);
hv_vmbus_free_vmbus_channel(new_channel);
}
+
+ mtx_lock(&vmbus_chwait_lock);
+ vmbus_devcnt++;
+ mtx_unlock(&vmbus_chwait_lock);
+ wakeup(&vmbus_devcnt);
}
void
@@ -384,6 +400,11 @@ vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr)
memcpy(copied, hdr, sizeof(*copied));
hv_queue_work_item(vmbus_channel_on_offer_internal, copied);
+
+ mtx_lock(&vmbus_chwait_lock);
+ if ((vmbus_chancnt & VMBUS_CHANCNT_DONE) == 0)
+ vmbus_chancnt++;
+ mtx_unlock(&vmbus_chwait_lock);
}
static void
@@ -475,6 +496,11 @@ vmbus_channel_on_offer_rescind_internal(void *context)
static void
vmbus_channel_on_offers_delivered(hv_vmbus_channel_msg_header* hdr)
{
+
+ mtx_lock(&vmbus_chwait_lock);
+ vmbus_chancnt |= VMBUS_CHANCNT_DONE;
+ mtx_unlock(&vmbus_chwait_lock);
+ wakeup(&vmbus_chancnt);
}
/**
@@ -752,3 +778,18 @@ vmbus_select_outgoing_channel(struct hv_vmbus_channel *primary)
return(outgoing_channel);
}
+
+void
+vmbus_scan(void)
+{
+ uint32_t chancnt;
+
+ mtx_lock(&vmbus_chwait_lock);
+ while ((vmbus_chancnt & VMBUS_CHANCNT_DONE) == 0)
+ mtx_sleep(&vmbus_chancnt, &vmbus_chwait_lock, 0, "waitch", 0);
+ chancnt = vmbus_chancnt & ~VMBUS_CHANCNT_DONE;
+
+ while (vmbus_devcnt != chancnt)
+ mtx_sleep(&vmbus_devcnt, &vmbus_chwait_lock, 0, "waitdev", 0);
+ mtx_unlock(&vmbus_chwait_lock);
+}
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
index c3e53d6..6e73da6 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
@@ -326,7 +326,6 @@ int
hv_vmbus_child_device_register(struct hv_device *child_dev)
{
device_t child;
- int ret = 0;
if (bootverbose) {
char name[40];
@@ -338,10 +337,6 @@ hv_vmbus_child_device_register(struct hv_device *child_dev)
child_dev->device = child;
device_set_ivars(child, child_dev);
- mtx_lock(&Giant);
- ret = device_probe_and_attach(child);
- mtx_unlock(&Giant);
-
return (0);
}
@@ -562,6 +557,11 @@ vmbus_bus_init(void)
goto cleanup1;
hv_vmbus_request_channel_offers();
+
+ vmbus_scan();
+ bus_generic_attach(vmbus_devp);
+ device_printf(vmbus_devp, "device scan, probe and attach done\n");
+
return (ret);
cleanup1:
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index d13cd95..e2b797d 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -751,6 +751,9 @@ void hv_vmbus_on_events(int cpu);
void hv_et_init(void);
void hv_et_intr(struct trapframe*);
+/* Wait for device creation */
+void vmbus_scan(void);
+
/*
* The guest OS needs to register the guest ID with the hypervisor.
* The guest ID is a 64 bit entity and the structure of this ID is
OpenPOWER on IntegriCloud