aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/1507-drm-amdgpu-Add-flag-for-KFD-to-allocate-a-doorbell-B.patch
blob: 1904495fdcaa5dcf58d28f2d4658d57eb0be9fea (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
From f4eb09eaf0feb309763d54a7a10cfe7c732f8bf2 Mon Sep 17 00:00:00 2001
From: Felix Kuehling <Felix.Kuehling@amd.com>
Date: Fri, 16 Sep 2016 15:48:13 -0400
Subject: [PATCH 1507/4131] drm/amdgpu: Add flag for KFD to allocate a doorbell
 BO

Uses a scatter-gather table to set up a BO that represents a doorbell
page. This enables existing GPUVM code to map a doorbell page for GPU
access, which is needed for GPU-initiated dispatches to user mode
queues.

Change-Id: Icdf95e91648a0cd1adb3beed5bbb7cd851d7f7c3
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 49 +++++++++++++++++++++---
 drivers/gpu/drm/amd/include/kgd_kfd_interface.h  |  1 +
 2 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 34072aa..fefdfe2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -294,7 +294,7 @@ static int amdgpu_amdkfd_gpuvm_clear_bo(struct amdgpu_device *adev,
 static int __alloc_memory_of_gpu(struct kgd_dev *kgd, uint64_t va,
 		uint64_t size, void *vm, struct kgd_mem **mem,
 		uint64_t *offset, void **kptr, struct kfd_process_device *pdd,
-		u32 domain, u64 flags, bool aql_queue,
+		u32 domain, u64 flags, struct sg_table *sg, bool aql_queue,
 		bool readonly, bool execute, bool no_sub, bool userptr)
 {
 	struct amdgpu_device *adev;
@@ -344,7 +344,7 @@ static int __alloc_memory_of_gpu(struct kgd_dev *kgd, uint64_t va,
 	 * in the CPU domain, get moved to GTT when pinned. */
 	ret = amdgpu_bo_create(adev, size, byte_align, false,
 				alloc_domain,
-			       flags, NULL, NULL, &bo);
+			       flags, sg, NULL, &bo);
 	if (ret != 0) {
 		pr_err("amdkfd: failed to create BO on domain %d. ret %d\n",
 				alloc_domain, ret);
@@ -764,6 +764,24 @@ static int map_bo_to_gpuvm(struct amdgpu_device *adev, struct amdgpu_bo *bo,
 	return ret;
 }
 
+static struct sg_table *create_doorbell_sg(uint64_t addr, uint32_t size)
+{
+	struct sg_table *sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+
+	if (!sg)
+		return NULL;
+	if (sg_alloc_table(sg, 1, GFP_KERNEL)) {
+		kfree(sg);
+		return NULL;
+	}
+	sg->sgl->dma_address = addr;
+	sg->sgl->length = size;
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+	sg->sgl->dma_length = size;
+#endif
+	return sg;
+}
+
 #define BOOL_TO_STR(b)	(b == true) ? "true" : "false"
 
 int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
@@ -776,6 +794,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 	u64 alloc_flag;
 	uint32_t domain;
 	uint64_t *temp_offset;
+	struct sg_table *sg = NULL;
 
 	if (!(flags & ALLOC_MEM_FLAGS_NONPAGED)) {
 		pr_err("amdgpu: current hw doesn't support paged memory\n");
@@ -791,7 +810,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 	readonly  = (flags & ALLOC_MEM_FLAGS_READONLY) ? true : false;
 	execute   = (flags & ALLOC_MEM_FLAGS_EXECUTE_ACCESS) ? true : false;
 	no_sub    = (flags & ALLOC_MEM_FLAGS_NO_SUBSTITUTE) ? true : false;
-	userptr = (flags & ALLOC_MEM_FLAGS_USERPTR) ? true : false;
+	userptr   = (flags & ALLOC_MEM_FLAGS_USERPTR) ? true : false;
 
 	if (userptr && kptr) {
 		pr_err("amdgpu: userptr can't be mapped to kernel\n");
@@ -801,8 +820,6 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 	/*
 	 * Check on which domain to allocate BO
 	 */
-	if (offset && !userptr)
-		*offset = 0;
 	if (flags & ALLOC_MEM_FLAGS_VRAM) {
 		domain = AMDGPU_GEM_DOMAIN_VRAM;
 		alloc_flag = AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
@@ -814,8 +831,20 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 		domain = AMDGPU_GEM_DOMAIN_GTT;
 		alloc_flag = 0;
 		temp_offset = offset;
+	} else if (flags & ALLOC_MEM_FLAGS_DOORBELL) {
+		domain = AMDGPU_GEM_DOMAIN_GTT;
+		alloc_flag = 0;
+		temp_offset = offset;
+		if (size > UINT_MAX)
+			return -EINVAL;
+		sg = create_doorbell_sg(*offset, size);
+		if (!sg)
+			return -ENOMEM;
 	}
 
+	if (offset && !userptr)
+		*offset = 0;
+
 	pr_debug("amdgpu: allocating BO domain %d alloc_flag 0x%llu public %s readonly %s execute %s no substitue %s va 0x%llx\n",
 			domain,
 			alloc_flag,
@@ -827,7 +856,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 
 	return __alloc_memory_of_gpu(kgd, va, size, vm, mem,
 			temp_offset, kptr, pdd, domain,
-			alloc_flag,
+			alloc_flag, sg,
 			aql_queue, readonly, execute,
 			no_sub, userptr);
 }
@@ -879,6 +908,14 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
 
 	unreserve_bo_and_vms(&ctx, false);
 
+	/* If the SG is not NULL, it's one we created for a doorbell
+	 * BO. We need to free it.
+	 */
+	if (mem->data2.bo->tbo.sg) {
+		sg_free_table(mem->data2.bo->tbo.sg);
+		kfree(mem->data2.bo->tbo.sg);
+	}
+
 	/* Free the BO*/
 	amdgpu_bo_unref(&mem->data2.bo);
 	kfree(mem);
diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
index 39d2807..db3ed48 100644
--- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
@@ -142,6 +142,7 @@ struct tile_config {
 #define ALLOC_MEM_FLAGS_VRAM			(1 << 0)
 #define ALLOC_MEM_FLAGS_GTT				(1 << 1)
 #define ALLOC_MEM_FLAGS_USERPTR			(1 << 2)
+#define ALLOC_MEM_FLAGS_DOORBELL		(1 << 3)
 
 /*
  * Allocation flags attributes/access options.
-- 
2.7.4