drivers/gpu/drm/omapdrm/omap_dmm_tiler.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
Extension
.c
Size
30512 bytes
Lines
1225
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

if (err) {
			dev_err(dmm->dev,
				"%s: error (engine%d). PAT_STATUS: 0x%08x\n",
				__func__, engine->id, r);
			return -EFAULT;
		}

		if ((r & wait_mask) == wait_mask)
			break;

		if (--i == 0) {
			dev_err(dmm->dev,
				"%s: timeout (engine%d). PAT_STATUS: 0x%08x\n",
				__func__, engine->id, r);
			return -ETIMEDOUT;
		}

		udelay(1);
	}

	return 0;
}

static void release_engine(struct refill_engine *engine)
{
	unsigned long flags;

	spin_lock_irqsave(&list_lock, flags);
	list_add(&engine->idle_node, &omap_dmm->idle_head);
	spin_unlock_irqrestore(&list_lock, flags);

	atomic_inc(&omap_dmm->engine_counter);
	wake_up_interruptible(&omap_dmm->engine_queue);
}

static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
{
	struct dmm *dmm = arg;
	u32 status = dmm_read(dmm, DMM_PAT_IRQSTATUS);
	int i;

	/* ack IRQ */
	dmm_write(dmm, status, DMM_PAT_IRQSTATUS);

	for (i = 0; i < dmm->num_engines; i++) {
		if (status & DMM_IRQSTAT_ERR_MASK)
			dev_err(dmm->dev,
				"irq error(engine%d): IRQSTAT 0x%02x\n",
				i, status & 0xff);

		if (status & DMM_IRQSTAT_LST) {
			if (dmm->engines[i].async)
				release_engine(&dmm->engines[i]);

			complete(&dmm->engines[i].compl);
		}

		status >>= 8;
	}

	return IRQ_HANDLED;
}

/*
 * Get a handle for a DMM transaction
 */
static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
{
	struct dmm_txn *txn = NULL;
	struct refill_engine *engine = NULL;
	int ret;
	unsigned long flags;


	/* wait until an engine is available */
	ret = wait_event_interruptible(omap_dmm->engine_queue,
		atomic_add_unless(&omap_dmm->engine_counter, -1, 0));
	if (ret)
		return ERR_PTR(ret);

	/* grab an idle engine */
	spin_lock_irqsave(&list_lock, flags);
	if (!list_empty(&dmm->idle_head)) {
		engine = list_entry(dmm->idle_head.next, struct refill_engine,
					idle_node);
		list_del(&engine->idle_node);
	}
	spin_unlock_irqrestore(&list_lock, flags);

	BUG_ON(!engine);

Annotation

Implementation Notes