drivers/hv/channel.c

Source file repositories/reference/linux-study-clean/drivers/hv/channel.c

File Facts

System
Linux kernel
Corpus path
drivers/hv/channel.c
Extension
.c
Size
38088 bytes
Lines
1299
Domain
Driver Families
Bucket
drivers/hv
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!msgbody) {
			struct vmbus_channel_msginfo *pos = NULL;
			struct vmbus_channel_msginfo *tmp = NULL;
			/*
			 * Free up all the allocated messages.
			 */
			list_for_each_entry_safe(pos, tmp,
				&msgheader->submsglist,
				msglistentry) {

				list_del(&pos->msglistentry);
				kfree(pos);
			}
			kfree(msgheader);
			return -ENOMEM;
		}

		msgbody->msgsize = msgsize;
		gpadl_body = (struct vmbus_channel_gpadl_body *)msgbody->msg;

		/*
		 * Gpadl is u32 and we are using a pointer which could
		 * be 64-bit
		 * This is governed by the guest/host protocol and
		 * so the hypervisor guarantees that this is ok.
		 */
		for (i = 0; i < pfncurr; i++)
			gpadl_body->pfn[i] = hv_gpadl_hvpfn(type,
				kbuffer, size, send_offset, pfnsum + i);

		/* add to msg header */
		list_add_tail(&msgbody->msglistentry, &msgheader->submsglist);
		pfnsum += pfncurr;
		pfnleft -= pfncurr;
	}

	return 0;
}

static void vmbus_free_channel_msginfo(struct vmbus_channel_msginfo *msginfo)
{
	struct vmbus_channel_msginfo *submsginfo, *tmp;

	if (!msginfo)
		return;

	list_for_each_entry_safe(submsginfo, tmp, &msginfo->submsglist,
				 msglistentry) {
		kfree(submsginfo);
	}

	kfree(msginfo);
}

/*
 * __vmbus_establish_gpadl - Establish a GPADL for a buffer or ringbuffer
 *
 * @channel: a channel
 * @type: the type of the corresponding GPADL, only meaningful for the guest.
 * @kbuffer: from kmalloc or vmalloc
 * @size: page-size multiple
 * @send_offset: the offset (in bytes) where the send ring buffer starts,
 *              should be 0 for BUFFER type gpadl
 * @gpadl_handle: some funky thing
 */
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;
	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) {
		gpadl->decrypted = false;
		return ret;
	}

	gpadl->decrypted = !((channel->co_external_memory && type == HV_GPADL_BUFFER) ||
		(channel->co_ring_buffer && type == HV_GPADL_RING));

Annotation

Implementation Notes