From fd2b520f2fd84d8d6f1953877a95d4965b2102e2 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Fri, 25 Nov 2016 06:12:18 +0000 Subject: [PATCH] hyperv/vmbus: Don't close unopened channels. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8566 --- sys/dev/hyperv/vmbus/vmbus_chan.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c index b749fe1f632..e1dac88c3c3 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