summaryrefslogtreecommitdiff
path: root/gxp-dma-fence.c
blob: 7bcc11b90049c4f40d37c3881d77934a3a4bf11d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// SPDX-License-Identifier: GPL-2.0
/*
 * GXP support for DMA fence.
 *
 * Copyright (C) 2023 Google LLC
 */

#include <linux/slab.h>

#include <gcip/gcip-dma-fence.h>

#include "gxp-dma-fence.h"
#include "gxp-internal.h"
#include "gxp-vd.h"
#include "gxp.h"

static const char *gxp_get_driver_name(struct dma_fence *fence)
{
	return GXP_NAME;
}

static void gxp_dma_fence_release(struct dma_fence *fence)
{
	struct gxp_dma_fence *gxp_fence = to_gxp_fence(fence);
	struct gxp_virtual_device *vd = gxp_fence->vd;

	mutex_lock(&vd->fence_list_lock);
	list_del(&gxp_fence->fence_list);
	mutex_unlock(&vd->fence_list_lock);
	gxp_vd_put(vd);
	gcip_dma_fence_exit(&gxp_fence->gfence);
	kfree(gxp_fence);
}

static const struct dma_fence_ops gxp_dma_fence_ops = {
	.get_driver_name = gxp_get_driver_name,
	.get_timeline_name = gcip_dma_fence_get_timeline_name,
	.wait = dma_fence_default_wait,
	.enable_signaling = gcip_dma_fence_always_true,
	.release = gxp_dma_fence_release,
};

static int gxp_dma_fence_after_init(struct gcip_dma_fence *gfence)
{
	struct gxp_dma_fence *gxp_fence =
		container_of(gfence, struct gxp_dma_fence, gfence);
	struct gxp_virtual_device *vd = gxp_fence->vd;

	mutex_lock(&vd->fence_list_lock);
	list_add_tail(&gxp_fence->fence_list, &vd->gxp_fence_list);
	mutex_unlock(&vd->fence_list_lock);

	return 0;
}

int gxp_dma_fence_create(struct gxp_dev *gxp, struct gxp_virtual_device *vd,
			 struct gxp_create_sync_fence_data *datap)
{
	struct gcip_dma_fence_data data = {
		.timeline_name = datap->timeline_name,
		.ops = &gxp_dma_fence_ops,
		.seqno = datap->seqno,
		.after_init = gxp_dma_fence_after_init,
	};
	struct gxp_dma_fence *gxp_fence =
		kzalloc(sizeof(*gxp_fence), GFP_KERNEL);
	int ret;

	if (!gxp_fence)
		return -ENOMEM;

	gxp_fence->vd = gxp_vd_get(vd);
	ret = gcip_dma_fence_init(gxp->gfence_mgr, &gxp_fence->gfence, &data);
	if (!ret)
		datap->fence = data.fence;
	/*
	 * We don't need to kfree(gxp_fence) on error because that's called in
	 * gxp_dma_fence_release.
	 */

	return ret;
}