aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelix Kuehling <Felix.Kuehling@amd.com>2017-12-08 23:08:49 -0500
committerOded Gabbay <oded.gabbay@gmail.com>2017-12-08 23:08:49 -0500
commit174de876d6d02f7159363495a3f34461ba91d3ee (patch)
tree4336dfd0390744be6d1f232e75a0018a7703b323 /drivers
parent5108d768408abc80e4e8d99f5b406a73cb04056b (diff)
drm/amdkfd: Group up CRAT related functions
Take CRAT related functions out of kfd_topology.c and place them in kfd_crat.c. This is the initial step of supporting more CRAT features, i.e. creating virtual CRAT table for KFD devices without CRAT. v2: Minor cleanup that was missed previously because code moved around Signed-off-by: Amber Lin <Amber.Lin@amd.com> Signed-off-by: Kent Russell <kent.russell@amd.com> Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com> Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/amdkfd/Makefile2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.c350
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.h5
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.c334
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.h3
5 files changed, 362 insertions, 332 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile
index 67e2c42a5e65..a317e76ffb5e 100644
--- a/drivers/gpu/drm/amd/amdkfd/Makefile
+++ b/drivers/gpu/drm/amd/amdkfd/Makefile
@@ -35,7 +35,7 @@ amdkfd-y := kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \
35 kfd_process_queue_manager.o kfd_device_queue_manager.o \ 35 kfd_process_queue_manager.o kfd_device_queue_manager.o \
36 kfd_device_queue_manager_cik.o kfd_device_queue_manager_vi.o \ 36 kfd_device_queue_manager_cik.o kfd_device_queue_manager_vi.o \
37 kfd_interrupt.o kfd_events.o cik_event_interrupt.o \ 37 kfd_interrupt.o kfd_events.o cik_event_interrupt.o \
38 kfd_dbgdev.o kfd_dbgmgr.o 38 kfd_dbgdev.o kfd_dbgmgr.o kfd_crat.o
39 39
40amdkfd-$(CONFIG_DEBUG_FS) += kfd_debugfs.o 40amdkfd-$(CONFIG_DEBUG_FS) += kfd_debugfs.o
41 41
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
new file mode 100644
index 000000000000..f2dda6012b77
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -0,0 +1,350 @@
1/*
2 * Copyright 2015-2017 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include <linux/acpi.h>
23#include "kfd_crat.h"
24#include "kfd_topology.h"
25
26static int topology_crat_parsed;
27extern struct list_head topology_device_list;
28extern struct kfd_system_properties sys_props;
29
30static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev,
31 struct crat_subtype_computeunit *cu)
32{
33 dev->node_props.cpu_cores_count = cu->num_cpu_cores;
34 dev->node_props.cpu_core_id_base = cu->processor_id_low;
35 if (cu->hsa_capability & CRAT_CU_FLAGS_IOMMU_PRESENT)
36 dev->node_props.capability |= HSA_CAP_ATS_PRESENT;
37
38 pr_info("CU CPU: cores=%d id_base=%d\n", cu->num_cpu_cores,
39 cu->processor_id_low);
40}
41
42static void kfd_populated_cu_info_gpu(struct kfd_topology_device *dev,
43 struct crat_subtype_computeunit *cu)
44{
45 dev->node_props.simd_id_base = cu->processor_id_low;
46 dev->node_props.simd_count = cu->num_simd_cores;
47 dev->node_props.lds_size_in_kb = cu->lds_size_in_kb;
48 dev->node_props.max_waves_per_simd = cu->max_waves_simd;
49 dev->node_props.wave_front_size = cu->wave_front_size;
50 dev->node_props.mem_banks_count = cu->num_banks;
51 dev->node_props.array_count = cu->num_arrays;
52 dev->node_props.cu_per_simd_array = cu->num_cu_per_array;
53 dev->node_props.simd_per_cu = cu->num_simd_per_cu;
54 dev->node_props.max_slots_scratch_cu = cu->max_slots_scatch_cu;
55 if (cu->hsa_capability & CRAT_CU_FLAGS_HOT_PLUGGABLE)
56 dev->node_props.capability |= HSA_CAP_HOT_PLUGGABLE;
57 pr_info("CU GPU: id_base=%d\n", cu->processor_id_low);
58}
59
60/* kfd_parse_subtype_cu is called when the topology mutex is already acquired */
61static int kfd_parse_subtype_cu(struct crat_subtype_computeunit *cu)
62{
63 struct kfd_topology_device *dev;
64 int i = 0;
65
66 pr_info("Found CU entry in CRAT table with proximity_domain=%d caps=%x\n",
67 cu->proximity_domain, cu->hsa_capability);
68 list_for_each_entry(dev, &topology_device_list, list) {
69 if (cu->proximity_domain == i) {
70 if (cu->flags & CRAT_CU_FLAGS_CPU_PRESENT)
71 kfd_populated_cu_info_cpu(dev, cu);
72
73 if (cu->flags & CRAT_CU_FLAGS_GPU_PRESENT)
74 kfd_populated_cu_info_gpu(dev, cu);
75 break;
76 }
77 i++;
78 }
79
80 return 0;
81}
82
83/*
84 * kfd_parse_subtype_mem is called when the topology mutex is
85 * already acquired
86 */
87static int kfd_parse_subtype_mem(struct crat_subtype_memory *mem)
88{
89 struct kfd_mem_properties *props;
90 struct kfd_topology_device *dev;
91 int i = 0;
92
93 pr_info("Found memory entry in CRAT table with proximity_domain=%d\n",
94 mem->proximity_domain);
95 list_for_each_entry(dev, &topology_device_list, list) {
96 if (mem->proximity_domain == i) {
97 props = kfd_alloc_struct(props);
98 if (!props)
99 return -ENOMEM;
100
101 if (dev->node_props.cpu_cores_count == 0)
102 props->heap_type = HSA_MEM_HEAP_TYPE_FB_PRIVATE;
103 else
104 props->heap_type = HSA_MEM_HEAP_TYPE_SYSTEM;
105
106 if (mem->flags & CRAT_MEM_FLAGS_HOT_PLUGGABLE)
107 props->flags |= HSA_MEM_FLAGS_HOT_PLUGGABLE;
108 if (mem->flags & CRAT_MEM_FLAGS_NON_VOLATILE)
109 props->flags |= HSA_MEM_FLAGS_NON_VOLATILE;
110
111 props->size_in_bytes =
112 ((uint64_t)mem->length_high << 32) +
113 mem->length_low;
114 props->width = mem->width;
115
116 dev->mem_bank_count++;
117 list_add_tail(&props->list, &dev->mem_props);
118
119 break;
120 }
121 i++;
122 }
123
124 return 0;
125}
126
127/*
128 * kfd_parse_subtype_cache is called when the topology mutex
129 * is already acquired
130 */
131static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache)
132{
133 struct kfd_cache_properties *props;
134 struct kfd_topology_device *dev;
135 uint32_t id;
136
137 id = cache->processor_id_low;
138
139 pr_info("Found cache entry in CRAT table with processor_id=%d\n", id);
140 list_for_each_entry(dev, &topology_device_list, list)
141 if (id == dev->node_props.cpu_core_id_base ||
142 id == dev->node_props.simd_id_base) {
143 props = kfd_alloc_struct(props);
144 if (!props)
145 return -ENOMEM;
146
147 props->processor_id_low = id;
148 props->cache_level = cache->cache_level;
149 props->cache_size = cache->cache_size;
150 props->cacheline_size = cache->cache_line_size;
151 props->cachelines_per_tag = cache->lines_per_tag;
152 props->cache_assoc = cache->associativity;
153 props->cache_latency = cache->cache_latency;
154
155 if (cache->flags & CRAT_CACHE_FLAGS_DATA_CACHE)
156 props->cache_type |= HSA_CACHE_TYPE_DATA;
157 if (cache->flags & CRAT_CACHE_FLAGS_INST_CACHE)
158 props->cache_type |= HSA_CACHE_TYPE_INSTRUCTION;
159 if (cache->flags & CRAT_CACHE_FLAGS_CPU_CACHE)
160 props->cache_type |= HSA_CACHE_TYPE_CPU;
161 if (cache->flags & CRAT_CACHE_FLAGS_SIMD_CACHE)
162 props->cache_type |= HSA_CACHE_TYPE_HSACU;
163
164 dev->cache_count++;
165 dev->node_props.caches_count++;
166 list_add_tail(&props->list, &dev->cache_props);
167
168 break;
169 }
170
171 return 0;
172}
173
174/*
175 * kfd_parse_subtype_iolink is called when the topology mutex
176 * is already acquired
177 */
178static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink)
179{
180 struct kfd_iolink_properties *props;
181 struct kfd_topology_device *dev;
182 uint32_t i = 0;
183 uint32_t id_from;
184 uint32_t id_to;
185
186 id_from = iolink->proximity_domain_from;
187 id_to = iolink->proximity_domain_to;
188
189 pr_info("Found IO link entry in CRAT table with id_from=%d\n", id_from);
190 list_for_each_entry(dev, &topology_device_list, list) {
191 if (id_from == i) {
192 props = kfd_alloc_struct(props);
193 if (!props)
194 return -ENOMEM;
195
196 props->node_from = id_from;
197 props->node_to = id_to;
198 props->ver_maj = iolink->version_major;
199 props->ver_min = iolink->version_minor;
200
201 /*
202 * weight factor (derived from CDIR), currently always 1
203 */
204 props->weight = 1;
205
206 props->min_latency = iolink->minimum_latency;
207 props->max_latency = iolink->maximum_latency;
208 props->min_bandwidth = iolink->minimum_bandwidth_mbs;
209 props->max_bandwidth = iolink->maximum_bandwidth_mbs;
210 props->rec_transfer_size =
211 iolink->recommended_transfer_size;
212
213 dev->io_link_count++;
214 dev->node_props.io_links_count++;
215 list_add_tail(&props->list, &dev->io_link_props);
216
217 break;
218 }
219 i++;
220 }
221
222 return 0;
223}
224
225static int kfd_parse_subtype(struct crat_subtype_generic *sub_type_hdr)
226{
227 struct crat_subtype_computeunit *cu;
228 struct crat_subtype_memory *mem;
229 struct crat_subtype_cache *cache;
230 struct crat_subtype_iolink *iolink;
231 int ret = 0;
232
233 switch (sub_type_hdr->type) {
234 case CRAT_SUBTYPE_COMPUTEUNIT_AFFINITY:
235 cu = (struct crat_subtype_computeunit *)sub_type_hdr;
236 ret = kfd_parse_subtype_cu(cu);
237 break;
238 case CRAT_SUBTYPE_MEMORY_AFFINITY:
239 mem = (struct crat_subtype_memory *)sub_type_hdr;
240 ret = kfd_parse_subtype_mem(mem);
241 break;
242 case CRAT_SUBTYPE_CACHE_AFFINITY:
243 cache = (struct crat_subtype_cache *)sub_type_hdr;
244 ret = kfd_parse_subtype_cache(cache);
245 break;
246 case CRAT_SUBTYPE_TLB_AFFINITY:
247 /*
248 * For now, nothing to do here
249 */
250 pr_info("Found TLB entry in CRAT table (not processing)\n");
251 break;
252 case CRAT_SUBTYPE_CCOMPUTE_AFFINITY:
253 /*
254 * For now, nothing to do here
255 */
256 pr_info("Found CCOMPUTE entry in CRAT table (not processing)\n");
257 break;
258 case CRAT_SUBTYPE_IOLINK_AFFINITY:
259 iolink = (struct crat_subtype_iolink *)sub_type_hdr;
260 ret = kfd_parse_subtype_iolink(iolink);
261 break;
262 default:
263 pr_warn("Unknown subtype %d in CRAT\n",
264 sub_type_hdr->type);
265 }
266
267 return ret;
268}
269
270int kfd_parse_crat_table(void *crat_image)
271{
272 struct kfd_topology_device *top_dev;
273 struct crat_subtype_generic *sub_type_hdr;
274 uint16_t node_id;
275 int ret;
276 struct crat_header *crat_table = (struct crat_header *)crat_image;
277 uint16_t num_nodes;
278 uint32_t image_len;
279
280 if (!crat_image)
281 return -EINVAL;
282
283 num_nodes = crat_table->num_domains;
284 image_len = crat_table->length;
285
286 pr_info("Parsing CRAT table with %d nodes\n", num_nodes);
287
288 for (node_id = 0; node_id < num_nodes; node_id++) {
289 top_dev = kfd_create_topology_device();
290 if (!top_dev) {
291 kfd_release_live_view();
292 return -ENOMEM;
293 }
294 }
295
296 sys_props.platform_id =
297 (*((uint64_t *)crat_table->oem_id)) & CRAT_OEMID_64BIT_MASK;
298 sys_props.platform_oem = *((uint64_t *)crat_table->oem_table_id);
299 sys_props.platform_rev = crat_table->revision;
300
301 sub_type_hdr = (struct crat_subtype_generic *)(crat_table+1);
302 while ((char *)sub_type_hdr + sizeof(struct crat_subtype_generic) <
303 ((char *)crat_image) + image_len) {
304 if (sub_type_hdr->flags & CRAT_SUBTYPE_FLAGS_ENABLED) {
305 ret = kfd_parse_subtype(sub_type_hdr);
306 if (ret != 0) {
307 kfd_release_live_view();
308 return ret;
309 }
310 }
311
312 sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
313 sub_type_hdr->length);
314 }
315
316 sys_props.generation_count++;
317 topology_crat_parsed = 1;
318
319 return 0;
320}
321
322int kfd_topology_get_crat_acpi(void *crat_image, size_t *size)
323{
324 struct acpi_table_header *crat_table;
325 acpi_status status;
326
327 if (!size)
328 return -EINVAL;
329
330 /*
331 * Fetch the CRAT table from ACPI
332 */
333 status = acpi_get_table(CRAT_SIGNATURE, 0, &crat_table);
334 if (status == AE_NOT_FOUND) {
335 pr_warn("CRAT table not found\n");
336 return -ENODATA;
337 } else if (ACPI_FAILURE(status)) {
338 const char *err = acpi_format_exception(status);
339
340 pr_err("CRAT table error: %s\n", err);
341 return -EINVAL;
342 }
343
344 if (*size >= crat_table->length && crat_image != NULL)
345 memcpy(crat_image, crat_table, crat_table->length);
346
347 *size = crat_table->length;
348
349 return 0;
350}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
index a374fa3d3ee6..920697b4469b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
@@ -127,7 +127,7 @@ struct crat_subtype_memory {
127 uint8_t length; 127 uint8_t length;
128 uint16_t reserved; 128 uint16_t reserved;
129 uint32_t flags; 129 uint32_t flags;
130 uint32_t promixity_domain; 130 uint32_t proximity_domain;
131 uint32_t base_addr_low; 131 uint32_t base_addr_low;
132 uint32_t base_addr_high; 132 uint32_t base_addr_high;
133 uint32_t length_low; 133 uint32_t length_low;
@@ -291,4 +291,7 @@ struct cdit_header {
291 291
292#pragma pack() 292#pragma pack()
293 293
294int kfd_topology_get_crat_acpi(void *crat_image, size_t *size);
295int kfd_parse_crat_table(void *crat_image);
296
294#endif /* KFD_CRAT_H_INCLUDED */ 297#endif /* KFD_CRAT_H_INCLUDED */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 9b9824f97de5..b6cf785d0138 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -34,9 +34,8 @@
34#include "kfd_topology.h" 34#include "kfd_topology.h"
35#include "kfd_device_queue_manager.h" 35#include "kfd_device_queue_manager.h"
36 36
37static struct list_head topology_device_list; 37struct list_head topology_device_list;
38static int topology_crat_parsed; 38struct kfd_system_properties sys_props;
39static struct kfd_system_properties sys_props;
40 39
41static DECLARE_RWSEM(topology_lock); 40static DECLARE_RWSEM(topology_lock);
42 41
@@ -76,276 +75,6 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev)
76 return device; 75 return device;
77} 76}
78 77
79static int kfd_topology_get_crat_acpi(void *crat_image, size_t *size)
80{
81 struct acpi_table_header *crat_table;
82 acpi_status status;
83
84 if (!size)
85 return -EINVAL;
86
87 /*
88 * Fetch the CRAT table from ACPI
89 */
90 status = acpi_get_table(CRAT_SIGNATURE, 0, &crat_table);
91 if (status == AE_NOT_FOUND) {
92 pr_warn("CRAT table not found\n");
93 return -ENODATA;
94 } else if (ACPI_FAILURE(status)) {
95 const char *err = acpi_format_exception(status);
96
97 pr_err("CRAT table error: %s\n", err);
98 return -EINVAL;
99 }
100
101 if (*size >= crat_table->length && crat_image != NULL)
102 memcpy(crat_image, crat_table, crat_table->length);
103
104 *size = crat_table->length;
105
106 return 0;
107}
108
109static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev,
110 struct crat_subtype_computeunit *cu)
111{
112 dev->node_props.cpu_cores_count = cu->num_cpu_cores;
113 dev->node_props.cpu_core_id_base = cu->processor_id_low;
114 if (cu->hsa_capability & CRAT_CU_FLAGS_IOMMU_PRESENT)
115 dev->node_props.capability |= HSA_CAP_ATS_PRESENT;
116
117 pr_info("CU CPU: cores=%d id_base=%d\n", cu->num_cpu_cores,
118 cu->processor_id_low);
119}
120
121static void kfd_populated_cu_info_gpu(struct kfd_topology_device *dev,
122 struct crat_subtype_computeunit *cu)
123{
124 dev->node_props.simd_id_base = cu->processor_id_low;
125 dev->node_props.simd_count = cu->num_simd_cores;
126 dev->node_props.lds_size_in_kb = cu->lds_size_in_kb;
127 dev->node_props.max_waves_per_simd = cu->max_waves_simd;
128 dev->node_props.wave_front_size = cu->wave_front_size;
129 dev->node_props.mem_banks_count = cu->num_banks;
130 dev->node_props.array_count = cu->num_arrays;
131 dev->node_props.cu_per_simd_array = cu->num_cu_per_array;
132 dev->node_props.simd_per_cu = cu->num_simd_per_cu;
133 dev->node_props.max_slots_scratch_cu = cu->max_slots_scatch_cu;
134 if (cu->hsa_capability & CRAT_CU_FLAGS_HOT_PLUGGABLE)
135 dev->node_props.capability |= HSA_CAP_HOT_PLUGGABLE;
136 pr_info("CU GPU: id_base=%d\n", cu->processor_id_low);
137}
138
139/* kfd_parse_subtype_cu is called when the topology mutex is already acquired */
140static int kfd_parse_subtype_cu(struct crat_subtype_computeunit *cu)
141{
142 struct kfd_topology_device *dev;
143 int i = 0;
144
145 pr_info("Found CU entry in CRAT table with proximity_domain=%d caps=%x\n",
146 cu->proximity_domain, cu->hsa_capability);
147 list_for_each_entry(dev, &topology_device_list, list) {
148 if (cu->proximity_domain == i) {
149 if (cu->flags & CRAT_CU_FLAGS_CPU_PRESENT)
150 kfd_populated_cu_info_cpu(dev, cu);
151
152 if (cu->flags & CRAT_CU_FLAGS_GPU_PRESENT)
153 kfd_populated_cu_info_gpu(dev, cu);
154 break;
155 }
156 i++;
157 }
158
159 return 0;
160}
161
162/*
163 * kfd_parse_subtype_mem is called when the topology mutex is
164 * already acquired
165 */
166static int kfd_parse_subtype_mem(struct crat_subtype_memory *mem)
167{
168 struct kfd_mem_properties *props;
169 struct kfd_topology_device *dev;
170 int i = 0;
171
172 pr_info("Found memory entry in CRAT table with proximity_domain=%d\n",
173 mem->promixity_domain);
174 list_for_each_entry(dev, &topology_device_list, list) {
175 if (mem->promixity_domain == i) {
176 props = kfd_alloc_struct(props);
177 if (props == NULL)
178 return -ENOMEM;
179
180 if (dev->node_props.cpu_cores_count == 0)
181 props->heap_type = HSA_MEM_HEAP_TYPE_FB_PRIVATE;
182 else
183 props->heap_type = HSA_MEM_HEAP_TYPE_SYSTEM;
184
185 if (mem->flags & CRAT_MEM_FLAGS_HOT_PLUGGABLE)
186 props->flags |= HSA_MEM_FLAGS_HOT_PLUGGABLE;
187 if (mem->flags & CRAT_MEM_FLAGS_NON_VOLATILE)
188 props->flags |= HSA_MEM_FLAGS_NON_VOLATILE;
189
190 props->size_in_bytes =
191 ((uint64_t)mem->length_high << 32) +
192 mem->length_low;
193 props->width = mem->width;
194
195 dev->mem_bank_count++;
196 list_add_tail(&props->list, &dev->mem_props);
197
198 break;
199 }
200 i++;
201 }
202
203 return 0;
204}
205
206/*
207 * kfd_parse_subtype_cache is called when the topology mutex
208 * is already acquired
209 */
210static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache)
211{
212 struct kfd_cache_properties *props;
213 struct kfd_topology_device *dev;
214 uint32_t id;
215
216 id = cache->processor_id_low;
217
218 pr_info("Found cache entry in CRAT table with processor_id=%d\n", id);
219 list_for_each_entry(dev, &topology_device_list, list)
220 if (id == dev->node_props.cpu_core_id_base ||
221 id == dev->node_props.simd_id_base) {
222 props = kfd_alloc_struct(props);
223 if (props == NULL)
224 return -ENOMEM;
225
226 props->processor_id_low = id;
227 props->cache_level = cache->cache_level;
228 props->cache_size = cache->cache_size;
229 props->cacheline_size = cache->cache_line_size;
230 props->cachelines_per_tag = cache->lines_per_tag;
231 props->cache_assoc = cache->associativity;
232 props->cache_latency = cache->cache_latency;
233
234 if (cache->flags & CRAT_CACHE_FLAGS_DATA_CACHE)
235 props->cache_type |= HSA_CACHE_TYPE_DATA;
236 if (cache->flags & CRAT_CACHE_FLAGS_INST_CACHE)
237 props->cache_type |= HSA_CACHE_TYPE_INSTRUCTION;
238 if (cache->flags & CRAT_CACHE_FLAGS_CPU_CACHE)
239 props->cache_type |= HSA_CACHE_TYPE_CPU;
240 if (cache->flags & CRAT_CACHE_FLAGS_SIMD_CACHE)
241 props->cache_type |= HSA_CACHE_TYPE_HSACU;
242
243 dev->cache_count++;
244 dev->node_props.caches_count++;
245 list_add_tail(&props->list, &dev->cache_props);
246
247 break;
248 }
249
250 return 0;
251}
252
253/*
254 * kfd_parse_subtype_iolink is called when the topology mutex
255 * is already acquired
256 */
257static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink)
258{
259 struct kfd_iolink_properties *props;
260 struct kfd_topology_device *dev;
261 uint32_t i = 0;
262 uint32_t id_from;
263 uint32_t id_to;
264
265 id_from = iolink->proximity_domain_from;
266 id_to = iolink->proximity_domain_to;
267
268 pr_info("Found IO link entry in CRAT table with id_from=%d\n", id_from);
269 list_for_each_entry(dev, &topology_device_list, list) {
270 if (id_from == i) {
271 props = kfd_alloc_struct(props);
272 if (props == NULL)
273 return -ENOMEM;
274
275 props->node_from = id_from;
276 props->node_to = id_to;
277 props->ver_maj = iolink->version_major;
278 props->ver_min = iolink->version_minor;
279
280 /*
281 * weight factor (derived from CDIR), currently always 1
282 */
283 props->weight = 1;
284
285 props->min_latency = iolink->minimum_latency;
286 props->max_latency = iolink->maximum_latency;
287 props->min_bandwidth = iolink->minimum_bandwidth_mbs;
288 props->max_bandwidth = iolink->maximum_bandwidth_mbs;
289 props->rec_transfer_size =
290 iolink->recommended_transfer_size;
291
292 dev->io_link_count++;
293 dev->node_props.io_links_count++;
294 list_add_tail(&props->list, &dev->io_link_props);
295
296 break;
297 }
298 i++;
299 }
300
301 return 0;
302}
303
304static int kfd_parse_subtype(struct crat_subtype_generic *sub_type_hdr)
305{
306 struct crat_subtype_computeunit *cu;
307 struct crat_subtype_memory *mem;
308 struct crat_subtype_cache *cache;
309 struct crat_subtype_iolink *iolink;
310 int ret = 0;
311
312 switch (sub_type_hdr->type) {
313 case CRAT_SUBTYPE_COMPUTEUNIT_AFFINITY:
314 cu = (struct crat_subtype_computeunit *)sub_type_hdr;
315 ret = kfd_parse_subtype_cu(cu);
316 break;
317 case CRAT_SUBTYPE_MEMORY_AFFINITY:
318 mem = (struct crat_subtype_memory *)sub_type_hdr;
319 ret = kfd_parse_subtype_mem(mem);
320 break;
321 case CRAT_SUBTYPE_CACHE_AFFINITY:
322 cache = (struct crat_subtype_cache *)sub_type_hdr;
323 ret = kfd_parse_subtype_cache(cache);
324 break;
325 case CRAT_SUBTYPE_TLB_AFFINITY:
326 /*
327 * For now, nothing to do here
328 */
329 pr_info("Found TLB entry in CRAT table (not processing)\n");
330 break;
331 case CRAT_SUBTYPE_CCOMPUTE_AFFINITY:
332 /*
333 * For now, nothing to do here
334 */
335 pr_info("Found CCOMPUTE entry in CRAT table (not processing)\n");
336 break;
337 case CRAT_SUBTYPE_IOLINK_AFFINITY:
338 iolink = (struct crat_subtype_iolink *)sub_type_hdr;
339 ret = kfd_parse_subtype_iolink(iolink);
340 break;
341 default:
342 pr_warn("Unknown subtype (%d) in CRAT\n",
343 sub_type_hdr->type);
344 }
345
346 return ret;
347}
348
349static void kfd_release_topology_device(struct kfd_topology_device *dev) 78static void kfd_release_topology_device(struct kfd_topology_device *dev)
350{ 79{
351 struct kfd_mem_properties *mem; 80 struct kfd_mem_properties *mem;
@@ -380,7 +109,7 @@ static void kfd_release_topology_device(struct kfd_topology_device *dev)
380 sys_props.num_devices--; 109 sys_props.num_devices--;
381} 110}
382 111
383static void kfd_release_live_view(void) 112void kfd_release_live_view(void)
384{ 113{
385 struct kfd_topology_device *dev; 114 struct kfd_topology_device *dev;
386 115
@@ -393,7 +122,7 @@ static void kfd_release_live_view(void)
393 memset(&sys_props, 0, sizeof(sys_props)); 122 memset(&sys_props, 0, sizeof(sys_props));
394} 123}
395 124
396static struct kfd_topology_device *kfd_create_topology_device(void) 125struct kfd_topology_device *kfd_create_topology_device(void)
397{ 126{
398 struct kfd_topology_device *dev; 127 struct kfd_topology_device *dev;
399 128
@@ -413,58 +142,6 @@ static struct kfd_topology_device *kfd_create_topology_device(void)
413 return dev; 142 return dev;
414} 143}
415 144
416static int kfd_parse_crat_table(void *crat_image)
417{
418 struct kfd_topology_device *top_dev;
419 struct crat_subtype_generic *sub_type_hdr;
420 uint16_t node_id;
421 int ret;
422 struct crat_header *crat_table = (struct crat_header *)crat_image;
423 uint16_t num_nodes;
424 uint32_t image_len;
425
426 if (!crat_image)
427 return -EINVAL;
428
429 num_nodes = crat_table->num_domains;
430 image_len = crat_table->length;
431
432 pr_info("Parsing CRAT table with %d nodes\n", num_nodes);
433
434 for (node_id = 0; node_id < num_nodes; node_id++) {
435 top_dev = kfd_create_topology_device();
436 if (!top_dev) {
437 kfd_release_live_view();
438 return -ENOMEM;
439 }
440 }
441
442 sys_props.platform_id =
443 (*((uint64_t *)crat_table->oem_id)) & CRAT_OEMID_64BIT_MASK;
444 sys_props.platform_oem = *((uint64_t *)crat_table->oem_table_id);
445 sys_props.platform_rev = crat_table->revision;
446
447 sub_type_hdr = (struct crat_subtype_generic *)(crat_table+1);
448 while ((char *)sub_type_hdr + sizeof(struct crat_subtype_generic) <
449 ((char *)crat_image) + image_len) {
450 if (sub_type_hdr->flags & CRAT_SUBTYPE_FLAGS_ENABLED) {
451 ret = kfd_parse_subtype(sub_type_hdr);
452 if (ret != 0) {
453 kfd_release_live_view();
454 return ret;
455 }
456 }
457
458 sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
459 sub_type_hdr->length);
460 }
461
462 sys_props.generation_count++;
463 topology_crat_parsed = 1;
464
465 return 0;
466}
467
468 145
469#define sysfs_show_gen_prop(buffer, fmt, ...) \ 146#define sysfs_show_gen_prop(buffer, fmt, ...) \
470 snprintf(buffer, PAGE_SIZE, "%s"fmt, buffer, __VA_ARGS__) 147 snprintf(buffer, PAGE_SIZE, "%s"fmt, buffer, __VA_ARGS__)
@@ -1016,7 +693,6 @@ int kfd_topology_init(void)
1016 */ 693 */
1017 INIT_LIST_HEAD(&topology_device_list); 694 INIT_LIST_HEAD(&topology_device_list);
1018 init_rwsem(&topology_lock); 695 init_rwsem(&topology_lock);
1019 topology_crat_parsed = 0;
1020 696
1021 memset(&sys_props, 0, sizeof(sys_props)); 697 memset(&sys_props, 0, sizeof(sys_props));
1022 698
@@ -1219,7 +895,7 @@ int kfd_topology_remove_device(struct kfd_dev *gpu)
1219 895
1220 up_write(&topology_lock); 896 up_write(&topology_lock);
1221 897
1222 if (res == 0) 898 if (!res)
1223 kfd_notify_gpu_change(gpu_id, 0); 899 kfd_notify_gpu_change(gpu_id, 0);
1224 900
1225 return res; 901 return res;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
index c3ddb9b95ff8..999645809028 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
@@ -164,6 +164,7 @@ struct kfd_system_properties {
164 struct attribute attr_props; 164 struct attribute attr_props;
165}; 165};
166 166
167 167struct kfd_topology_device *kfd_create_topology_device(void);
168void kfd_release_live_view(void);
168 169
169#endif /* __KFD_TOPOLOGY_H__ */ 170#endif /* __KFD_TOPOLOGY_H__ */