drivers/dma/amd/ae4dma/ae4dma-dev.c

Source file repositories/reference/linux-study-clean/drivers/dma/amd/ae4dma/ae4dma-dev.c

File Facts

System
Linux kernel
Corpus path
drivers/dma/amd/ae4dma/ae4dma-dev.c
Extension
.c
Size
3912 bytes
Lines
158
Domain
Driver Families
Bucket
drivers/dma
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

while ((ae4cmd_q->dridx != cridx) && !list_empty(&ae4cmd_q->cmd)) {
			cmd = list_first_entry(&ae4cmd_q->cmd, struct pt_cmd, entry);
			list_del(&cmd->entry);

			ae4_check_status_error(ae4cmd_q, ae4cmd_q->dridx);
			cmd->pt_cmd_callback(cmd->data, cmd->ret);

			ae4cmd_q->q_cmd_count--;
			ae4cmd_q->dridx = (ae4cmd_q->dridx + 1) % CMD_Q_LEN;

			complete_all(&ae4cmd_q->cmp);
		}
		mutex_unlock(&ae4cmd_q->cmd_lock);
	}
}

static irqreturn_t ae4_core_irq_handler(int irq, void *data)
{
	struct ae4_cmd_queue *ae4cmd_q = data;
	struct pt_cmd_queue *cmd_q;
	struct pt_device *pt;
	u32 status;

	cmd_q = &ae4cmd_q->cmd_q;
	pt = cmd_q->pt;

	pt->total_interrupts++;
	atomic64_inc(&ae4cmd_q->intr_cnt);

	status = readl(cmd_q->reg_control + AE4_INTR_STS_OFF);
	if (status & BIT(0)) {
		status &= GENMASK(31, 1);
		writel(status, cmd_q->reg_control + AE4_INTR_STS_OFF);
	}

	wake_up(&ae4cmd_q->q_w);

	return IRQ_HANDLED;
}

void ae4_destroy_work(struct ae4_device *ae4)
{
	struct ae4_cmd_queue *ae4cmd_q;
	int i;

	for (i = 0; i < ae4->cmd_q_count; i++) {
		ae4cmd_q = &ae4->ae4cmd_q[i];

		if (!ae4cmd_q->pws)
			break;

		cancel_delayed_work_sync(&ae4cmd_q->p_work);
		destroy_workqueue(ae4cmd_q->pws);
	}
}

int ae4_core_init(struct ae4_device *ae4)
{
	struct pt_device *pt = &ae4->pt;
	struct ae4_cmd_queue *ae4cmd_q;
	struct device *dev = pt->dev;
	struct pt_cmd_queue *cmd_q;
	int i, ret = 0;

	writel(max_hw_q, pt->io_regs);

	for (i = 0; i < max_hw_q; i++) {
		ae4cmd_q = &ae4->ae4cmd_q[i];
		ae4cmd_q->id = ae4->cmd_q_count;
		ae4->cmd_q_count++;

		cmd_q = &ae4cmd_q->cmd_q;
		cmd_q->pt = pt;

		cmd_q->reg_control = pt->io_regs + ((i + 1) * AE4_Q_SZ);

		ret = devm_request_irq(dev, ae4->ae4_irq[i], ae4_core_irq_handler, 0,
				       dev_name(pt->dev), ae4cmd_q);
		if (ret)
			return ret;

		cmd_q->qsize = Q_SIZE(sizeof(struct ae4dma_desc));

		cmd_q->qbase = dmam_alloc_coherent(dev, cmd_q->qsize, &cmd_q->qbase_dma,
						   GFP_KERNEL);
		if (!cmd_q->qbase)
			return -ENOMEM;
	}

	for (i = 0; i < ae4->cmd_q_count; i++) {

Annotation

Implementation Notes