drivers/hv/mshv_synic.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hv/mshv_synic.c
Extension
.c
Size
21766 bytes
Lines
874
Domain
Driver Families
Bucket
drivers/hv
Inferred role
Driver Families: implementation source
Status
source 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 (ring->ring_full) {
			/*
			 * Ring is marked full, but we would have consumed all
			 * the messages. Notify the hypervisor that ring is now
			 * empty and check again.
			 */
			ring->ring_full = 0;
			hv_call_notify_port_ring_empty(sint_index);
			message = ring->data[tail];
		}

		if (!message) {
			ring->signal_masked = 0;
			/*
			 * Unmask the signal and sync with hypervisor
			 * before one last check for any message.
			 */
			mb();
			message = ring->data[tail];

			/*
			 * Ok, lets bail out.
			 */
			if (!message)
				return 0;
		}

		ring->signal_masked = 1;
	}

	/*
	 * Clear the message in the ring buffer.
	 */
	ring->data[tail] = 0;

	if (++tail == HV_SYNIC_EVENT_RING_MESSAGE_COUNT)
		tail = 0;

	(*synic_eventring_tail)[sint_index] = tail;

	return message;
}

static bool
mshv_doorbell_isr(struct hv_message *msg)
{
	struct hv_notification_message_payload *notification;
	u32 port;

	if (msg->header.message_type != HVMSG_SYNIC_SINT_INTERCEPT)
		return false;

	notification = (struct hv_notification_message_payload *)msg->u.payload;
	if (notification->sint_index != HV_SYNIC_DOORBELL_SINT_INDEX)
		return false;

	while ((port = synic_event_ring_get_queued_port(HV_SYNIC_DOORBELL_SINT_INDEX))) {
		struct port_table_info ptinfo = { 0 };

		if (mshv_portid_lookup(port, &ptinfo)) {
			pr_debug("Failed to get port info from port_table!\n");
			continue;
		}

		if (ptinfo.hv_port_type != HV_PORT_TYPE_DOORBELL) {
			pr_debug("Not a doorbell port!, port: %d, port_type: %d\n",
				 port, ptinfo.hv_port_type);
			continue;
		}

		/* Invoke the callback */
		ptinfo.hv_port_doorbell.doorbell_cb(port,
						 ptinfo.hv_port_doorbell.data);
	}

	return true;
}

static bool mshv_async_call_completion_isr(struct hv_message *msg)
{
	bool handled = false;
	struct hv_async_completion_message_payload *async_msg;
	struct mshv_partition *partition;
	u64 partition_id;

	if (msg->header.message_type != HVMSG_ASYNC_CALL_COMPLETION)
		goto out;

	async_msg =
		(struct hv_async_completion_message_payload *)msg->u.payload;

Annotation

Implementation Notes