in channel.c [457:571]
static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
enum hv_gpadl_type type, void *kbuffer,
u32 size, u32 send_offset,
struct vmbus_gpadl *gpadl)
{
struct vmbus_channel_gpadl_header *gpadlmsg;
struct vmbus_channel_gpadl_body *gpadl_body;
struct vmbus_channel_msginfo *msginfo = NULL;
struct vmbus_channel_msginfo *submsginfo, *tmp;
struct list_head *curr;
u32 next_gpadl_handle;
unsigned long flags;
int ret = 0;
next_gpadl_handle =
(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo);
if (ret)
return ret;
ret = set_memory_decrypted((unsigned long)kbuffer,
PFN_UP(size));
if (ret) {
dev_warn(&channel->device_obj->device,
"Failed to set host visibility for new GPADL %d.\n",
ret);
return ret;
}
init_completion(&msginfo->waitevent);
msginfo->waiting_channel = channel;
gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
gpadlmsg->child_relid = channel->offermsg.child_relid;
gpadlmsg->gpadl = next_gpadl_handle;
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_add_tail(&msginfo->msglistentry,
&vmbus_connection.chn_msg_list);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
if (channel->rescind) {
ret = -ENODEV;
goto cleanup;
}
ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
sizeof(*msginfo), true);
trace_vmbus_establish_gpadl_header(gpadlmsg, ret);
if (ret != 0)
goto cleanup;
list_for_each(curr, &msginfo->submsglist) {
submsginfo = (struct vmbus_channel_msginfo *)curr;
gpadl_body =
(struct vmbus_channel_gpadl_body *)submsginfo->msg;
gpadl_body->header.msgtype =
CHANNELMSG_GPADL_BODY;
gpadl_body->gpadl = next_gpadl_handle;
ret = vmbus_post_msg(gpadl_body,
submsginfo->msgsize - sizeof(*submsginfo),
true);
trace_vmbus_establish_gpadl_body(gpadl_body, ret);
if (ret != 0)
goto cleanup;
}
wait_for_completion(&msginfo->waitevent);
if (msginfo->response.gpadl_created.creation_status != 0) {
pr_err("Failed to establish GPADL: err = 0x%x\n",
msginfo->response.gpadl_created.creation_status);
ret = -EDQUOT;
goto cleanup;
}
if (channel->rescind) {
ret = -ENODEV;
goto cleanup;
}
/* At this point, we received the gpadl created msg */
gpadl->gpadl_handle = gpadlmsg->gpadl;
gpadl->buffer = kbuffer;
gpadl->size = size;
cleanup:
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_del(&msginfo->msglistentry);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
list_for_each_entry_safe(submsginfo, tmp, &msginfo->submsglist,
msglistentry) {
kfree(submsginfo);
}
kfree(msginfo);
if (ret)
set_memory_encrypted((unsigned long)kbuffer,
PFN_UP(size));
return ret;
}