in hv_balloon.c [1656:1762]
static int balloon_connect_vsp(struct hv_device *dev)
{
struct dm_version_request version_req;
struct dm_capabilities cap_msg;
unsigned long t;
int ret;
ret = vmbus_open(dev->channel, dm_ring_size, dm_ring_size, NULL, 0,
balloon_onchannelcallback, dev);
if (ret)
return ret;
/*
* Initiate the hand shake with the host and negotiate
* a version that the host can support. We start with the
* highest version number and go down if the host cannot
* support it.
*/
memset(&version_req, 0, sizeof(struct dm_version_request));
version_req.hdr.type = DM_VERSION_REQUEST;
version_req.hdr.size = sizeof(struct dm_version_request);
version_req.hdr.trans_id = atomic_inc_return(&trans_id);
version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN10;
version_req.is_last_attempt = 0;
dm_device.version = version_req.version.version;
ret = vmbus_sendpacket(dev->channel, &version_req,
sizeof(struct dm_version_request),
(unsigned long)NULL, VM_PKT_DATA_INBAND, 0);
if (ret)
goto out;
t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto out;
}
/*
* If we could not negotiate a compatible version with the host
* fail the probe function.
*/
if (dm_device.state == DM_INIT_ERROR) {
ret = -EPROTO;
goto out;
}
pr_info("Using Dynamic Memory protocol version %u.%u\n",
DYNMEM_MAJOR_VERSION(dm_device.version),
DYNMEM_MINOR_VERSION(dm_device.version));
/*
* Now submit our capabilities to the host.
*/
memset(&cap_msg, 0, sizeof(struct dm_capabilities));
cap_msg.hdr.type = DM_CAPABILITIES_REPORT;
cap_msg.hdr.size = sizeof(struct dm_capabilities);
cap_msg.hdr.trans_id = atomic_inc_return(&trans_id);
/*
* When hibernation (i.e. virtual ACPI S4 state) is enabled, the host
* currently still requires the bits to be set, so we have to add code
* to fail the host's hot-add and balloon up/down requests, if any.
*/
cap_msg.caps.cap_bits.balloon = 1;
cap_msg.caps.cap_bits.hot_add = 1;
/*
* Specify our alignment requirements as it relates
* memory hot-add. Specify 128MB alignment.
*/
cap_msg.caps.cap_bits.hot_add_alignment = 7;
/*
* Currently the host does not use these
* values and we set them to what is done in the
* Windows driver.
*/
cap_msg.min_page_cnt = 0;
cap_msg.max_page_number = -1;
ret = vmbus_sendpacket(dev->channel, &cap_msg,
sizeof(struct dm_capabilities),
(unsigned long)NULL, VM_PKT_DATA_INBAND, 0);
if (ret)
goto out;
t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto out;
}
/*
* If the host does not like our capabilities,
* fail the probe function.
*/
if (dm_device.state == DM_INIT_ERROR) {
ret = -EPROTO;
goto out;
}
return 0;
out:
vmbus_close(dev->channel);
return ret;
}