diff options
author | Felix Kuehling <Felix.Kuehling@amd.com> | 2017-12-08 23:08:49 -0500 |
---|---|---|
committer | Oded Gabbay <oded.gabbay@gmail.com> | 2017-12-08 23:08:49 -0500 |
commit | 174de876d6d02f7159363495a3f34461ba91d3ee (patch) | |
tree | 4336dfd0390744be6d1f232e75a0018a7703b323 /drivers | |
parent | 5108d768408abc80e4e8d99f5b406a73cb04056b (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/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 350 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_crat.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 334 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_topology.h | 3 |
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 | ||
40 | amdkfd-$(CONFIG_DEBUG_FS) += kfd_debugfs.o | 40 | amdkfd-$(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 | |||
26 | static int topology_crat_parsed; | ||
27 | extern struct list_head topology_device_list; | ||
28 | extern struct kfd_system_properties sys_props; | ||
29 | |||
30 | static 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 | |||
42 | static 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 */ | ||
61 | static 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 | */ | ||
87 | static 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 | */ | ||
131 | static 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 | */ | ||
178 | static 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 | |||
225 | static 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 | |||
270 | int 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 | |||
322 | int 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 | ||
294 | int kfd_topology_get_crat_acpi(void *crat_image, size_t *size); | ||
295 | int 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 | ||
37 | static struct list_head topology_device_list; | 37 | struct list_head topology_device_list; |
38 | static int topology_crat_parsed; | 38 | struct kfd_system_properties sys_props; |
39 | static struct kfd_system_properties sys_props; | ||
40 | 39 | ||
41 | static DECLARE_RWSEM(topology_lock); | 40 | static 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 | ||
79 | static 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 | |||
109 | static 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 | |||
121 | static 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 */ | ||
140 | static 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 | */ | ||
166 | static 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 | */ | ||
210 | static 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 | */ | ||
257 | static 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 | |||
304 | static 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 | |||
349 | static void kfd_release_topology_device(struct kfd_topology_device *dev) | 78 | static 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 | ||
383 | static void kfd_release_live_view(void) | 112 | void 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 | ||
396 | static struct kfd_topology_device *kfd_create_topology_device(void) | 125 | struct 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 | ||
416 | static 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 | 167 | struct kfd_topology_device *kfd_create_topology_device(void); | |
168 | void kfd_release_live_view(void); | ||
168 | 169 | ||
169 | #endif /* __KFD_TOPOLOGY_H__ */ | 170 | #endif /* __KFD_TOPOLOGY_H__ */ |