diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 3761b2864eef..8b985b2f31a7 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -94,6 +94,11 @@ extern hyperv_tc64_t hyperv_tc64; extern u_int hyperv_features; /* CPUID_HV_MSR_ */ extern u_int hyperv_ver_major; +/* + * Vmbus version after negotiation with host. + */ +extern uint32_t vmbus_current_version; + #endif /* _KERNEL */ #endif /* _HYPERV_H_ */ diff --git a/sys/dev/hyperv/include/vmbus.h b/sys/dev/hyperv/include/vmbus.h index 4b0060e9241d..6f9cb6459dce 100644 --- a/sys/dev/hyperv/include/vmbus.h +++ b/sys/dev/hyperv/include/vmbus.h @@ -40,11 +40,15 @@ * 1.1 -- Windows 7 * 2.4 -- Windows 8 * 3.0 -- Windows 8.1 + * 4.0 -- Windows 10 + * 5.0 -- Newer Windows 10 */ #define VMBUS_VERSION_WS2008 ((0 << 16) | (13)) #define VMBUS_VERSION_WIN7 ((1 << 16) | (1)) #define VMBUS_VERSION_WIN8 ((2 << 16) | (4)) #define VMBUS_VERSION_WIN8_1 ((3 << 16) | (0)) +#define VMBUS_VERSION_WIN10 ((4 << 16) | (0)) +#define VMBUS_VERSION_WIN10_V5 ((5 << 16) | (0)) #define VMBUS_VERSION_MAJOR(ver) (((uint32_t)(ver)) >> 16) #define VMBUS_VERSION_MINOR(ver) (((uint32_t)(ver)) & 0xffff) diff --git a/sys/dev/hyperv/netvsc/hn_nvs.c b/sys/dev/hyperv/netvsc/hn_nvs.c index f21f989d876a..73a112c4e5e1 100644 --- a/sys/dev/hyperv/netvsc/hn_nvs.c +++ b/sys/dev/hyperv/netvsc/hn_nvs.c @@ -365,7 +365,7 @@ hn_nvs_disconn_rxbuf(struct hn_softc *sc) pause("lingtx", (200 * hz) / 1000); } - if (sc->hn_rxbuf_gpadl != 0) { + if (vmbus_current_version < VMBUS_VERSION_WIN10 && sc->hn_rxbuf_gpadl != 0) { /* * Disconnect RXBUF from primary channel. */ @@ -426,7 +426,7 @@ hn_nvs_disconn_chim(struct hn_softc *sc) pause("lingtx", (200 * hz) / 1000); } - if (sc->hn_chim_gpadl != 0) { + if (vmbus_current_version < VMBUS_VERSION_WIN10 && sc->hn_chim_gpadl != 0) { /* * Disconnect chimney sending buffer from primary channel. */ diff --git a/sys/dev/hyperv/netvsc/if_hn.c b/sys/dev/hyperv/netvsc/if_hn.c index d2eaa711dcbc..812bfa9ecbca 100644 --- a/sys/dev/hyperv/netvsc/if_hn.c +++ b/sys/dev/hyperv/netvsc/if_hn.c @@ -6630,6 +6630,38 @@ hn_synth_detach(struct hn_softc *sc) /* Detach all of the channels. */ hn_detach_allchans(sc); + if (vmbus_current_version >= VMBUS_VERSION_WIN10 && sc->hn_rxbuf_gpadl != 0) { + /* + * Host is post-Win2016, disconnect RXBUF from primary channel here. + */ + int error; + + error = vmbus_chan_gpadl_disconnect(sc->hn_prichan, + sc->hn_rxbuf_gpadl); + if (error) { + if_printf(sc->hn_ifp, + "rxbuf gpadl disconn failed: %d\n", error); + sc->hn_flags |= HN_FLAG_RXBUF_REF; + } + sc->hn_rxbuf_gpadl = 0; + } + + if (vmbus_current_version >= VMBUS_VERSION_WIN10 && sc->hn_chim_gpadl != 0) { + /* + * Host is post-Win2016, disconnect chimney sending buffer from + * primary channel here. + */ + int error; + + error = vmbus_chan_gpadl_disconnect(sc->hn_prichan, + sc->hn_chim_gpadl); + if (error) { + if_printf(sc->hn_ifp, + "chim gpadl disconn failed: %d\n", error); + sc->hn_flags |= HN_FLAG_CHIM_REF; + } + sc->hn_chim_gpadl = 0; + } sc->hn_flags &= ~HN_FLAG_SYNTH_ATTACHED; } diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c index b027752290be..baf41ee879af 100644 --- a/sys/dev/hyperv/vmbus/vmbus.c +++ b/sys/dev/hyperv/vmbus/vmbus.c @@ -138,7 +138,10 @@ SYSCTL_INT(_hw_vmbus, OID_AUTO, pin_evttask, CTLFLAG_RDTUN, extern inthand_t IDTVEC(vmbus_isr), IDTVEC(vmbus_isr_pti); +uint32_t vmbus_current_version; + static const uint32_t vmbus_version[] = { + VMBUS_VERSION_WIN10, VMBUS_VERSION_WIN8_1, VMBUS_VERSION_WIN8, VMBUS_VERSION_WIN7, @@ -412,6 +415,7 @@ vmbus_init(struct vmbus_softc *sc) error = vmbus_connect(sc, vmbus_version[i]); if (!error) { + vmbus_current_version = vmbus_version[i]; sc->vmbus_version = vmbus_version[i]; device_printf(sc->vmbus_dev, "version %u.%u\n", VMBUS_VERSION_MAJOR(sc->vmbus_version),