drivers/gpu/drm/qxl/qxl_cmd.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/qxl/qxl_cmd.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/qxl/qxl_cmd.c
Extension
.c
Size
16666 bytes
Lines
663
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

struct ring {
	struct qxl_ring_header      header;
	uint8_t                     elements[];
};

struct qxl_ring {
	struct ring	       *ring;
	int			element_size;
	int			n_elements;
	int			prod_notify;
	wait_queue_head_t      *push_event;
	spinlock_t             lock;
};

void qxl_ring_free(struct qxl_ring *ring)
{
	kfree(ring);
}

struct qxl_ring *
qxl_ring_create(struct qxl_ring_header *header,
		int element_size,
		int n_elements,
		int prod_notify,
		wait_queue_head_t *push_event)
{
	struct qxl_ring *ring;

	ring = kmalloc_obj(*ring);
	if (!ring)
		return NULL;

	ring->ring = (struct ring *)header;
	ring->element_size = element_size;
	ring->n_elements = n_elements;
	ring->prod_notify = prod_notify;
	ring->push_event = push_event;
	spin_lock_init(&ring->lock);
	return ring;
}

static int qxl_check_header(struct qxl_ring *ring)
{
	int ret;
	struct qxl_ring_header *header = &(ring->ring->header);
	unsigned long flags;

	spin_lock_irqsave(&ring->lock, flags);
	ret = header->prod - header->cons < header->num_items;
	if (ret == 0)
		header->notify_on_cons = header->cons + 1;
	spin_unlock_irqrestore(&ring->lock, flags);
	return ret;
}

int qxl_check_idle(struct qxl_ring *ring)
{
	int ret;
	struct qxl_ring_header *header = &(ring->ring->header);
	unsigned long flags;

	spin_lock_irqsave(&ring->lock, flags);
	ret = header->prod == header->cons;
	spin_unlock_irqrestore(&ring->lock, flags);
	return ret;
}

int qxl_ring_push(struct qxl_ring *ring,
		  const void *new_elt, bool interruptible)
{
	struct qxl_ring_header *header = &(ring->ring->header);
	uint8_t *elt;
	int idx, ret;
	unsigned long flags;

	spin_lock_irqsave(&ring->lock, flags);
	if (header->prod - header->cons == header->num_items) {
		header->notify_on_cons = header->cons + 1;
		mb();
		spin_unlock_irqrestore(&ring->lock, flags);
		if (!drm_can_sleep()) {
			while (!qxl_check_header(ring))
				udelay(1);
		} else {
			if (interruptible) {
				ret = wait_event_interruptible(*ring->push_event,
							       qxl_check_header(ring));
				if (ret)
					return ret;
			} else {

Annotation

Implementation Notes