drivers/accel/amdxdna/amdxdna_ctx.c

Source file repositories/reference/linux-study-clean/drivers/accel/amdxdna/amdxdna_ctx.c

File Facts

System
Linux kernel
Corpus path
drivers/accel/amdxdna/amdxdna_ctx.c
Extension
.c
Size
18186 bytes
Lines
740
Domain
Driver Families
Bucket
drivers/accel
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

struct amdxdna_fence {
	struct dma_fence	base;
	spinlock_t		lock; /* for base */
	struct amdxdna_hwctx	*hwctx;
};

static const char *amdxdna_fence_get_driver_name(struct dma_fence *fence)
{
	return KBUILD_MODNAME;
}

static const char *amdxdna_fence_get_timeline_name(struct dma_fence *fence)
{
	struct amdxdna_fence *xdna_fence;

	xdna_fence = container_of(fence, struct amdxdna_fence, base);

	return xdna_fence->hwctx->name;
}

static const struct dma_fence_ops fence_ops = {
	.get_driver_name = amdxdna_fence_get_driver_name,
	.get_timeline_name = amdxdna_fence_get_timeline_name,
};

static struct dma_fence *amdxdna_fence_create(struct amdxdna_hwctx *hwctx)
{
	struct amdxdna_fence *fence;

	fence = kzalloc_obj(*fence);
	if (!fence)
		return NULL;

	fence->hwctx = hwctx;
	spin_lock_init(&fence->lock);
	dma_fence_init(&fence->base, &fence_ops, &fence->lock, hwctx->id, 0);
	return &fence->base;
}

static void amdxdna_hwctx_release_expanded_heap(struct amdxdna_hwctx *hwctx)
{
	struct amdxdna_client *client = hwctx->client;
	struct amdxdna_gem_obj *heap;
	unsigned long heap_id;

	mutex_lock(&client->mm_lock);
	if (hwctx->last_attached_heap) {
		xa_for_each_range(&client->dev_heap_xa, heap_id, heap, 1,
				  hwctx->last_attached_heap) {
			amdxdna_gem_unpin(heap);
			drm_gem_object_put(to_gobj(heap));
		}
	}
	mutex_unlock(&client->mm_lock);
}

static void amdxdna_hwctx_destroy_rcu(struct amdxdna_hwctx *hwctx,
				      struct srcu_struct *ss)
{
	struct amdxdna_client *client = hwctx->client;
	struct amdxdna_dev *xdna = client->xdna;

	synchronize_srcu(ss);

	/* At this point, user is not able to submit new commands */
	xdna->dev_info->ops->hwctx_fini(hwctx);

	amdxdna_hwctx_release_expanded_heap(hwctx);
	kfree(hwctx->name);
	kfree(hwctx);
}

int amdxdna_hwctx_walk(struct amdxdna_client *client, void *arg,
		       int (*walk)(struct amdxdna_hwctx *hwctx, void *arg))
{
	struct amdxdna_hwctx *hwctx;
	unsigned long hwctx_id;
	int ret = 0, idx;

	idx = srcu_read_lock(&client->hwctx_srcu);
	amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
		ret = walk(hwctx, arg);
		if (ret)
			break;
	}
	srcu_read_unlock(&client->hwctx_srcu, idx);

	return ret;
}

Annotation

Implementation Notes