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

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

File Facts

System
Linux kernel
Corpus path
drivers/dma/amd/ptdma/ptdma-dev.c
Extension
.c
Size
8386 bytes
Lines
310
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

// SPDX-License-Identifier: GPL-2.0-only
/*
 * AMD Passthru DMA device driver
 * -- Based on the CCP driver
 *
 * Copyright (C) 2016,2021 Advanced Micro Devices, Inc.
 *
 * Author: Sanjay R Mehta <sanju.mehta@amd.com>
 * Author: Gary R Hook <gary.hook@amd.com>
 */

#include <linux/bitfield.h>
#include <linux/dma-mapping.h>
#include <linux/debugfs.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>

#include "ptdma.h"

/* Human-readable error strings */
static char *pt_error_codes[] = {
	"",
	"ERR 01: ILLEGAL_ENGINE",
	"ERR 03: ILLEGAL_FUNCTION_TYPE",
	"ERR 04: ILLEGAL_FUNCTION_MODE",
	"ERR 06: ILLEGAL_FUNCTION_SIZE",
	"ERR 08: ILLEGAL_FUNCTION_RSVD",
	"ERR 09: ILLEGAL_BUFFER_LENGTH",
	"ERR 10: VLSB_FAULT",
	"ERR 11: ILLEGAL_MEM_ADDR",
	"ERR 12: ILLEGAL_MEM_SEL",
	"ERR 13: ILLEGAL_CONTEXT_ID",
	"ERR 15: 0xF Reserved",
	"ERR 18: CMD_TIMEOUT",
	"ERR 19: IDMA0_AXI_SLVERR",
	"ERR 20: IDMA0_AXI_DECERR",
	"ERR 21: 0x15 Reserved",
	"ERR 22: IDMA1_AXI_SLAVE_FAULT",
	"ERR 23: IDMA1_AIXI_DECERR",
	"ERR 24: 0x18 Reserved",
	"ERR 27: 0x1B Reserved",
	"ERR 38: ODMA0_AXI_SLVERR",
	"ERR 39: ODMA0_AXI_DECERR",
	"ERR 40: 0x28 Reserved",
	"ERR 41: ODMA1_AXI_SLVERR",
	"ERR 42: ODMA1_AXI_DECERR",
	"ERR 43: LSB_PARITY_ERR",
};

static void pt_log_error(struct pt_device *d, int e)
{
	dev_err(d->dev, "PTDMA error: %s (0x%x)\n", pt_error_codes[e], e);
}

void pt_start_queue(struct pt_cmd_queue *cmd_q)
{
	/* Turn on the run bit */
	iowrite32(cmd_q->qcontrol | CMD_Q_RUN, cmd_q->reg_control);
}

void pt_stop_queue(struct pt_cmd_queue *cmd_q)
{
	/* Turn off the run bit */
	iowrite32(cmd_q->qcontrol & ~CMD_Q_RUN, cmd_q->reg_control);
}

static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd_q)
{
	bool soc = FIELD_GET(DWORD0_SOC, desc->dw0);
	u8 *q_desc = (u8 *)&cmd_q->qbase[cmd_q->qidx];
	u32 tail;
	unsigned long flags;

	if (soc) {
		desc->dw0 |= FIELD_PREP(DWORD0_IOC, desc->dw0);
		desc->dw0 &= ~DWORD0_SOC;
	}
	spin_lock_irqsave(&cmd_q->q_lock, flags);

	/* Copy 32-byte command descriptor to hw queue. */
	memcpy(q_desc, desc, 32);
	cmd_q->qidx = (cmd_q->qidx + 1) % CMD_Q_LEN;

	/* The data used by this command must be flushed to memory */
	wmb();

	/* Write the new tail address back to the queue register */
	tail = lower_32_bits(cmd_q->qdma_tail + cmd_q->qidx * Q_DESC_SIZE);

Annotation

Implementation Notes