drivers/gpu/drm/xen/xen_drm_front_evtchnl.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c
Extension
.c
Size
8734 bytes
Lines
366
Domain
Driver Families
Bucket
drivers/gpu
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

switch (resp->operation) {
		case XENDISPL_OP_PG_FLIP:
		case XENDISPL_OP_FB_ATTACH:
		case XENDISPL_OP_FB_DETACH:
		case XENDISPL_OP_DBUF_CREATE:
		case XENDISPL_OP_DBUF_DESTROY:
		case XENDISPL_OP_SET_CONFIG:
			evtchnl->u.req.resp_status = resp->status;
			complete(&evtchnl->u.req.completion);
			break;

		default:
			DRM_ERROR("Operation %d is not supported\n",
				  resp->operation);
			break;
		}
	}

	evtchnl->u.req.ring.rsp_cons = i;

	if (i != evtchnl->u.req.ring.req_prod_pvt) {
		int more_to_do;

		RING_FINAL_CHECK_FOR_RESPONSES(&evtchnl->u.req.ring,
					       more_to_do);
		if (more_to_do)
			goto again;
	} else {
		evtchnl->u.req.ring.sring->rsp_event = i + 1;
	}

	spin_unlock_irqrestore(&front_info->io_lock, flags);
	return IRQ_HANDLED;
}

static irqreturn_t evtchnl_interrupt_evt(int irq, void *dev_id)
{
	struct xen_drm_front_evtchnl *evtchnl = dev_id;
	struct xen_drm_front_info *front_info = evtchnl->front_info;
	struct xendispl_event_page *page = evtchnl->u.evt.page;
	u32 cons, prod;
	unsigned long flags;

	if (unlikely(evtchnl->state != EVTCHNL_STATE_CONNECTED))
		return IRQ_HANDLED;

	spin_lock_irqsave(&front_info->io_lock, flags);

	prod = page->in_prod;
	/* ensure we see ring contents up to prod */
	virt_rmb();
	if (prod == page->in_cons)
		goto out;

	for (cons = page->in_cons; cons != prod; cons++) {
		struct xendispl_evt *event;

		event = &XENDISPL_IN_RING_REF(page, cons);
		if (unlikely(event->id != evtchnl->evt_id++))
			continue;

		switch (event->type) {
		case XENDISPL_EVT_PG_FLIP:
			xen_drm_front_on_frame_done(front_info, evtchnl->index,
						    event->op.pg_flip.fb_cookie);
			break;
		}
	}
	page->in_cons = cons;
	/* ensure ring contents */
	virt_wmb();

out:
	spin_unlock_irqrestore(&front_info->io_lock, flags);
	return IRQ_HANDLED;
}

static void evtchnl_free(struct xen_drm_front_info *front_info,
			 struct xen_drm_front_evtchnl *evtchnl)
{
	void *page = NULL;

	if (evtchnl->type == EVTCHNL_TYPE_REQ)
		page = evtchnl->u.req.ring.sring;
	else if (evtchnl->type == EVTCHNL_TYPE_EVT)
		page = evtchnl->u.evt.page;
	if (!page)
		return;

	evtchnl->state = EVTCHNL_STATE_DISCONNECTED;

Annotation

Implementation Notes