aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hyperv/vmbus
diff options
context:
space:
mode:
authorSepherosa Ziehau <sephe@FreeBSD.org>2016-11-25 06:12:18 +0000
committerSepherosa Ziehau <sephe@FreeBSD.org>2016-11-25 06:12:18 +0000
commitfd2b520f2fd84d8d6f1953877a95d4965b2102e2 (patch)
tree4c544e0e3889206f02472ff5ed58f457086629b1 /sys/dev/hyperv/vmbus
parentba9238f89fdde615ca46c13953b430756e673091 (diff)
Notes
Diffstat (limited to 'sys/dev/hyperv/vmbus')
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_chan.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c
index b749fe1f63274..e1dac88c3c322 100644
--- a/sys/dev/hyperv/vmbus/vmbus_chan.c
+++ b/sys/dev/hyperv/vmbus/vmbus_chan.c
@@ -688,10 +688,28 @@ vmbus_chan_close_internal(struct vmbus_channel *chan)
struct vmbus_softc *sc = chan->ch_vmbus;
struct vmbus_msghc *mh;
struct vmbus_chanmsg_chclose *req;
+ uint32_t old_stflags;
int error;
- /* TODO: stringent check */
- atomic_clear_int(&chan->ch_stflags, VMBUS_CHAN_ST_OPENED);
+ /*
+ * NOTE:
+ * Sub-channels are closed upon their primary channel closing,
+ * so they can be closed even before they are opened.
+ */
+ for (;;) {
+ old_stflags = chan->ch_stflags;
+ if (atomic_cmpset_int(&chan->ch_stflags, old_stflags,
+ old_stflags & ~VMBUS_CHAN_ST_OPENED))
+ break;
+ }
+ if ((old_stflags & VMBUS_CHAN_ST_OPENED) == 0) {
+ /* Not opened yet; done */
+ if (bootverbose) {
+ vmbus_chan_printf(chan, "chan%u not opened\n",
+ chan->ch_id);
+ }
+ return;
+ }
/*
* Free this channel's sysctl tree attached to its device's