drivers/gpu/drm/xe/xe_range_fence.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xe/xe_range_fence.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_range_fence.c
Extension
.c
Size
4140 bytes
Lines
164
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

// SPDX-License-Identifier: MIT
/*
 * Copyright © 2023 Intel Corporation
 */

#include <linux/dma-fence.h>
#include <linux/interval_tree_generic.h>
#include <linux/slab.h>

#include "xe_macros.h"
#include "xe_range_fence.h"

#define XE_RANGE_TREE_START(_node)	((_node)->start)
#define XE_RANGE_TREE_LAST(_node)	((_node)->last)

INTERVAL_TREE_DEFINE(struct xe_range_fence, rb, u64, __subtree_last,
		     XE_RANGE_TREE_START, XE_RANGE_TREE_LAST, static,
		     xe_range_fence_tree);

static void
xe_range_fence_signal_notify(struct dma_fence *fence, struct dma_fence_cb *cb)
{
	struct xe_range_fence *rfence = container_of(cb, typeof(*rfence), cb);
	struct xe_range_fence_tree *tree = rfence->tree;

	llist_add(&rfence->link, &tree->list);
}

static bool __xe_range_fence_tree_cleanup(struct xe_range_fence_tree *tree)
{
	struct llist_node *node = llist_del_all(&tree->list);
	struct xe_range_fence *rfence, *next;

	llist_for_each_entry_safe(rfence, next, node, link) {
		xe_range_fence_tree_remove(rfence, &tree->root);
		dma_fence_put(rfence->fence);
		kfree(rfence);
	}

	return !!node;
}

/**
 * xe_range_fence_insert() - range fence insert
 * @tree: range fence tree to insert intoi
 * @rfence: range fence
 * @ops: range fence ops
 * @start: start address of range fence
 * @last: last address of range fence
 * @fence: dma fence which signals range fence can be removed + freed
 *
 * Return: 0 on success, non-zero on failure
 */
int xe_range_fence_insert(struct xe_range_fence_tree *tree,
			  struct xe_range_fence *rfence,
			  const struct xe_range_fence_ops *ops,
			  u64 start, u64 last, struct dma_fence *fence)
{
	int err = 0;

	__xe_range_fence_tree_cleanup(tree);

	if (dma_fence_is_signaled(fence))
		goto free;

	rfence->ops = ops;
	rfence->start = start;
	rfence->last = last;
	rfence->tree = tree;
	rfence->fence = dma_fence_get(fence);
	err = dma_fence_add_callback(fence, &rfence->cb,
				     xe_range_fence_signal_notify);
	if (err == -ENOENT) {
		dma_fence_put(fence);
		err = 0;
		goto free;
	} else if (err == 0) {
		xe_range_fence_tree_insert(rfence, &tree->root);
		return 0;
	} else {
		dma_fence_put(fence);
	}

free:
	if (ops->free)
		ops->free(rfence);

	return err;
}

Annotation

Implementation Notes