diff options
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_channel_mgmt.c | 41 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c | 10 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 3 |
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 |