hyperv/vmbus: Add supportive transaction wait function.

This function supports channel revocation properly.

MFC after:	1 week
Sponsored by:	Microsoft
Differential Revision:	https://reviews.freebsd.org/D8611
This commit is contained in:
Sepherosa Ziehau 2016-11-28 05:07:48 +00:00
parent faaba341e5
commit a54152eaa5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=309225
2 changed files with 37 additions and 0 deletions

View file

@ -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);

View file

@ -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);
}