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

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

File Facts

System
Linux kernel
Corpus path
drivers/dma/amd/ptdma/ptdma-dmaengine.c
Extension
.c
Size
16267 bytes
Lines
660
Domain
Driver Families
Bucket
drivers/dma
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (desc) {
			if (!desc->issued_to_hw) {
				/* No errors, keep going */
				if (desc->status != DMA_ERROR)
					return desc;
			}

			tx_desc = &desc->vd.tx;
			vd = &desc->vd;
		} else {
			tx_desc = NULL;
		}

		spin_lock_irqsave(&chan->vc.lock, flags);

		if (pt->ver != AE4_DMA_VERSION && desc) {
			if (desc->status != DMA_COMPLETE) {
				if (desc->status != DMA_ERROR)
					desc->status = DMA_COMPLETE;

				dma_cookie_complete(tx_desc);
				dma_descriptor_unmap(tx_desc);
				list_del(&desc->vd.node);
			} else {
				/* Don't handle it twice */
				tx_desc = NULL;
			}
		}

		desc = pt_next_dma_desc(chan);

		spin_unlock_irqrestore(&chan->vc.lock, flags);

		if (pt->ver != AE4_DMA_VERSION && tx_desc) {
			dmaengine_desc_get_callback_invoke(tx_desc, NULL);
			dma_run_dependencies(tx_desc);
			vchan_vdesc_fini(vd);
		}
	} while (desc);

	return NULL;
}

static inline bool ae4_core_queue_full(struct pt_cmd_queue *cmd_q)
{
	u32 front_wi = readl(cmd_q->reg_control + AE4_WR_IDX_OFF);
	u32 rear_ri = readl(cmd_q->reg_control + AE4_RD_IDX_OFF);

	if (((MAX_CMD_QLEN + front_wi - rear_ri) % MAX_CMD_QLEN)  >= (MAX_CMD_QLEN - 1))
		return true;

	return false;
}

static void pt_cmd_callback(void *data, int err)
{
	struct pt_dma_desc *desc = data;
	struct ae4_cmd_queue *ae4cmd_q;
	struct dma_chan *dma_chan;
	struct pt_dma_chan *chan;
	struct ae4_device *ae4;
	struct pt_device *pt;
	int ret;

	if (err == -EINPROGRESS)
		return;

	dma_chan = desc->vd.tx.chan;
	chan = to_pt_chan(dma_chan);
	pt = chan->pt;

	if (err)
		desc->status = DMA_ERROR;

	while (true) {
		if (pt->ver == AE4_DMA_VERSION) {
			ae4 = container_of(pt, struct ae4_device, pt);
			ae4cmd_q = &ae4->ae4cmd_q[chan->id];

			if (ae4cmd_q->q_cmd_count >= (CMD_Q_LEN - 1) ||
			    ae4_core_queue_full(&ae4cmd_q->cmd_q)) {
				wake_up(&ae4cmd_q->q_w);

				if (wait_for_completion_timeout(&ae4cmd_q->cmp,
								msecs_to_jiffies(AE4_TIME_OUT))
								== 0) {
					dev_err(pt->dev, "TIMEOUT %d:\n", ae4cmd_q->id);
					break;
				}

Annotation

Implementation Notes