aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hyperv
diff options
context:
space:
mode:
authorSepherosa Ziehau <sephe@FreeBSD.org>2016-11-28 05:07:48 +0000
committerSepherosa Ziehau <sephe@FreeBSD.org>2016-11-28 05:07:48 +0000
commita54152eaa5c3f98ef11fbdb22d11cf7d4c5cd34c (patch)
tree945e896b77680bce0a319749582718ca05385f22 /sys/dev/hyperv
parentfaaba341e529d89c60f7a19e9131220d6b61744a (diff)
Notes
Diffstat (limited to 'sys/dev/hyperv')
-rw-r--r--sys/dev/hyperv/include/vmbus.h3
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_chan.c34
2 files changed, 37 insertions, 0 deletions
diff --git a/sys/dev/hyperv/include/vmbus.h b/sys/dev/hyperv/include/vmbus.h
index 5fd9676c7053..a6dfe5b6a59e 100644
--- a/sys/dev/hyperv/include/vmbus.h
+++ b/sys/dev/hyperv/include/vmbus.h
@@ -116,6 +116,7 @@ struct vmbus_chan_br {
};
struct vmbus_channel;
+struct vmbus_xact;
struct vmbus_xact_ctx;
struct hyperv_guid;
struct task;
@@ -173,6 +174,8 @@ void vmbus_chan_run_task(struct vmbus_channel *chan,
void vmbus_chan_set_orphan(struct vmbus_channel *chan,
struct vmbus_xact_ctx *);
void vmbus_chan_unset_orphan(struct vmbus_channel *chan);
+const void *vmbus_chan_xact_wait(const struct vmbus_channel *chan,
+ struct vmbus_xact *xact, size_t *resp_len, bool can_sleep);
int vmbus_chan_gpadl_connect(struct vmbus_channel *chan,
bus_addr_t paddr, int size, uint32_t *gpadl);
diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c
index 0118439ba1e5..70e12c5e09df 100644
--- a/sys/dev/hyperv/vmbus/vmbus_chan.c
+++ b/sys/dev/hyperv/vmbus/vmbus_chan.c
@@ -1927,3 +1927,37 @@ vmbus_chan_unset_orphan(struct vmbus_channel *chan)
chan->ch_orphan_xact = NULL;
sx_xunlock(&chan->ch_orphan_lock);
}
+
+const void *
+vmbus_chan_xact_wait(const struct vmbus_channel *chan,
+ struct vmbus_xact *xact, size_t *resp_len, bool can_sleep)
+{
+ const void *ret;
+
+ if (can_sleep)
+ ret = vmbus_xact_wait(xact, resp_len);
+ else
+ ret = vmbus_xact_busywait(xact, resp_len);
+ if (vmbus_chan_is_revoked(chan)) {
+ /*
+ * This xact probably is interrupted, and the
+ * interruption can race the reply reception,
+ * so we have to make sure that there are nothing
+ * left on the RX bufring, i.e. this xact will
+ * not be touched, once this function returns.
+ *
+ * Since the hypervisor will not put more data
+ * onto the RX bufring once the channel is revoked,
+ * the following loop will be terminated, once all
+ * data are drained by the driver's channel
+ * callback.
+ */
+ while (!vmbus_chan_rx_empty(chan)) {
+ if (can_sleep)
+ pause("chxact", 1);
+ else
+ DELAY(1000);
+ }
+ }
+ return (ret);
+}