2437 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR MIT2/*3 * Copyright 2015-2022 Advanced Micro Devices, Inc.4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice shall be included in13 * all copies or substantial portions of the Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR21 * OTHER DEALINGS IN THE SOFTWARE.22 */23 24#include <linux/pci.h>25#include <linux/acpi.h>26#include "kfd_crat.h"27#include "kfd_priv.h"28#include "kfd_topology.h"29#include "amdgpu.h"30#include "amdgpu_amdkfd.h"31 32/* GPU Processor ID base for dGPUs for which VCRAT needs to be created.33 * GPU processor ID are expressed with Bit[31]=1.34 * The base is set to 0x8000_0000 + 0x1000 to avoid collision with GPU IDs35 * used in the CRAT.36 */37static uint32_t gpu_processor_id_low = 0x80001000;38 39/* Return the next available gpu_processor_id and increment it for next GPU40 * @total_cu_count - Total CUs present in the GPU including ones41 * masked off42 */43static inline unsigned int get_and_inc_gpu_processor_id(44 unsigned int total_cu_count)45{46 int current_id = gpu_processor_id_low;47 48 gpu_processor_id_low += total_cu_count;49 return current_id;50}51 52 53static struct kfd_gpu_cache_info kaveri_cache_info[] = {54 {55 /* TCP L1 Cache per CU */56 .cache_size = 16,57 .cache_level = 1,58 .cache_line_size = 64,59 .flags = (CRAT_CACHE_FLAGS_ENABLED |60 CRAT_CACHE_FLAGS_DATA_CACHE |61 CRAT_CACHE_FLAGS_SIMD_CACHE),62 .num_cu_shared = 1,63 },64 {65 /* Scalar L1 Instruction Cache (in SQC module) per bank */66 .cache_size = 16,67 .cache_level = 1,68 .cache_line_size = 64,69 .flags = (CRAT_CACHE_FLAGS_ENABLED |70 CRAT_CACHE_FLAGS_INST_CACHE |71 CRAT_CACHE_FLAGS_SIMD_CACHE),72 .num_cu_shared = 2,73 },74 {75 /* Scalar L1 Data Cache (in SQC module) per bank */76 .cache_size = 8,77 .cache_level = 1,78 .cache_line_size = 64,79 .flags = (CRAT_CACHE_FLAGS_ENABLED |80 CRAT_CACHE_FLAGS_DATA_CACHE |81 CRAT_CACHE_FLAGS_SIMD_CACHE),82 .num_cu_shared = 2,83 },84 85 /* TODO: Add L2 Cache information */86};87 88 89static struct kfd_gpu_cache_info carrizo_cache_info[] = {90 {91 /* TCP L1 Cache per CU */92 .cache_size = 16,93 .cache_level = 1,94 .cache_line_size = 64,95 .flags = (CRAT_CACHE_FLAGS_ENABLED |96 CRAT_CACHE_FLAGS_DATA_CACHE |97 CRAT_CACHE_FLAGS_SIMD_CACHE),98 .num_cu_shared = 1,99 },100 {101 /* Scalar L1 Instruction Cache (in SQC module) per bank */102 .cache_size = 32,103 .cache_level = 1,104 .cache_line_size = 64,105 .flags = (CRAT_CACHE_FLAGS_ENABLED |106 CRAT_CACHE_FLAGS_INST_CACHE |107 CRAT_CACHE_FLAGS_SIMD_CACHE),108 .num_cu_shared = 4,109 },110 {111 /* Scalar L1 Data Cache (in SQC module) per bank. */112 .cache_size = 16,113 .cache_level = 1,114 .cache_line_size = 64,115 .flags = (CRAT_CACHE_FLAGS_ENABLED |116 CRAT_CACHE_FLAGS_DATA_CACHE |117 CRAT_CACHE_FLAGS_SIMD_CACHE),118 .num_cu_shared = 4,119 },120 121 /* TODO: Add L2 Cache information */122};123 124#define hawaii_cache_info kaveri_cache_info125#define tonga_cache_info carrizo_cache_info126#define fiji_cache_info carrizo_cache_info127#define polaris10_cache_info carrizo_cache_info128#define polaris11_cache_info carrizo_cache_info129#define polaris12_cache_info carrizo_cache_info130#define vegam_cache_info carrizo_cache_info131 132/* NOTE: L1 cache information has been updated and L2/L3133 * cache information has been added for Vega10 and134 * newer ASICs. The unit for cache_size is KiB.135 * In future, check & update cache details136 * for every new ASIC is required.137 */138 139static struct kfd_gpu_cache_info vega10_cache_info[] = {140 {141 /* TCP L1 Cache per CU */142 .cache_size = 16,143 .cache_level = 1,144 .cache_line_size = 64,145 .flags = (CRAT_CACHE_FLAGS_ENABLED |146 CRAT_CACHE_FLAGS_DATA_CACHE |147 CRAT_CACHE_FLAGS_SIMD_CACHE),148 .num_cu_shared = 1,149 },150 {151 /* Scalar L1 Instruction Cache per SQC */152 .cache_size = 32,153 .cache_level = 1,154 .cache_line_size = 64,155 .flags = (CRAT_CACHE_FLAGS_ENABLED |156 CRAT_CACHE_FLAGS_INST_CACHE |157 CRAT_CACHE_FLAGS_SIMD_CACHE),158 .num_cu_shared = 3,159 },160 {161 /* Scalar L1 Data Cache per SQC */162 .cache_size = 16,163 .cache_level = 1,164 .cache_line_size = 64,165 .flags = (CRAT_CACHE_FLAGS_ENABLED |166 CRAT_CACHE_FLAGS_DATA_CACHE |167 CRAT_CACHE_FLAGS_SIMD_CACHE),168 .num_cu_shared = 3,169 },170 {171 /* L2 Data Cache per GPU (Total Tex Cache) */172 .cache_size = 4096,173 .cache_level = 2,174 .cache_line_size = 64,175 .flags = (CRAT_CACHE_FLAGS_ENABLED |176 CRAT_CACHE_FLAGS_DATA_CACHE |177 CRAT_CACHE_FLAGS_SIMD_CACHE),178 .num_cu_shared = 16,179 },180};181 182static struct kfd_gpu_cache_info raven_cache_info[] = {183 {184 /* TCP L1 Cache per CU */185 .cache_size = 16,186 .cache_level = 1,187 .cache_line_size = 64,188 .flags = (CRAT_CACHE_FLAGS_ENABLED |189 CRAT_CACHE_FLAGS_DATA_CACHE |190 CRAT_CACHE_FLAGS_SIMD_CACHE),191 .num_cu_shared = 1,192 },193 {194 /* Scalar L1 Instruction Cache per SQC */195 .cache_size = 32,196 .cache_level = 1,197 .cache_line_size = 64,198 .flags = (CRAT_CACHE_FLAGS_ENABLED |199 CRAT_CACHE_FLAGS_INST_CACHE |200 CRAT_CACHE_FLAGS_SIMD_CACHE),201 .num_cu_shared = 3,202 },203 {204 /* Scalar L1 Data Cache per SQC */205 .cache_size = 16,206 .cache_level = 1,207 .cache_line_size = 64,208 .flags = (CRAT_CACHE_FLAGS_ENABLED |209 CRAT_CACHE_FLAGS_DATA_CACHE |210 CRAT_CACHE_FLAGS_SIMD_CACHE),211 .num_cu_shared = 3,212 },213 {214 /* L2 Data Cache per GPU (Total Tex Cache) */215 .cache_size = 1024,216 .cache_level = 2,217 .cache_line_size = 64,218 .flags = (CRAT_CACHE_FLAGS_ENABLED |219 CRAT_CACHE_FLAGS_DATA_CACHE |220 CRAT_CACHE_FLAGS_SIMD_CACHE),221 .num_cu_shared = 11,222 },223};224 225static struct kfd_gpu_cache_info renoir_cache_info[] = {226 {227 /* TCP L1 Cache per CU */228 .cache_size = 16,229 .cache_level = 1,230 .cache_line_size = 64,231 .flags = (CRAT_CACHE_FLAGS_ENABLED |232 CRAT_CACHE_FLAGS_DATA_CACHE |233 CRAT_CACHE_FLAGS_SIMD_CACHE),234 .num_cu_shared = 1,235 },236 {237 /* Scalar L1 Instruction Cache per SQC */238 .cache_size = 32,239 .cache_level = 1,240 .cache_line_size = 64,241 .flags = (CRAT_CACHE_FLAGS_ENABLED |242 CRAT_CACHE_FLAGS_INST_CACHE |243 CRAT_CACHE_FLAGS_SIMD_CACHE),244 .num_cu_shared = 3,245 },246 {247 /* Scalar L1 Data Cache per SQC */248 .cache_size = 16,249 .cache_level = 1,250 .cache_line_size = 64,251 .flags = (CRAT_CACHE_FLAGS_ENABLED |252 CRAT_CACHE_FLAGS_DATA_CACHE |253 CRAT_CACHE_FLAGS_SIMD_CACHE),254 .num_cu_shared = 3,255 },256 {257 /* L2 Data Cache per GPU (Total Tex Cache) */258 .cache_size = 1024,259 .cache_level = 2,260 .cache_line_size = 64,261 .flags = (CRAT_CACHE_FLAGS_ENABLED |262 CRAT_CACHE_FLAGS_DATA_CACHE |263 CRAT_CACHE_FLAGS_SIMD_CACHE),264 .num_cu_shared = 8,265 },266};267 268static struct kfd_gpu_cache_info vega12_cache_info[] = {269 {270 /* TCP L1 Cache per CU */271 .cache_size = 16,272 .cache_level = 1,273 .cache_line_size = 64,274 .flags = (CRAT_CACHE_FLAGS_ENABLED |275 CRAT_CACHE_FLAGS_DATA_CACHE |276 CRAT_CACHE_FLAGS_SIMD_CACHE),277 .num_cu_shared = 1,278 },279 {280 /* Scalar L1 Instruction Cache per SQC */281 .cache_size = 32,282 .cache_level = 1,283 .cache_line_size = 64,284 .flags = (CRAT_CACHE_FLAGS_ENABLED |285 CRAT_CACHE_FLAGS_INST_CACHE |286 CRAT_CACHE_FLAGS_SIMD_CACHE),287 .num_cu_shared = 3,288 },289 {290 /* Scalar L1 Data Cache per SQC */291 .cache_size = 16,292 .cache_level = 1,293 .cache_line_size = 64,294 .flags = (CRAT_CACHE_FLAGS_ENABLED |295 CRAT_CACHE_FLAGS_DATA_CACHE |296 CRAT_CACHE_FLAGS_SIMD_CACHE),297 .num_cu_shared = 3,298 },299 {300 /* L2 Data Cache per GPU (Total Tex Cache) */301 .cache_size = 2048,302 .cache_level = 2,303 .cache_line_size = 64,304 .flags = (CRAT_CACHE_FLAGS_ENABLED |305 CRAT_CACHE_FLAGS_DATA_CACHE |306 CRAT_CACHE_FLAGS_SIMD_CACHE),307 .num_cu_shared = 5,308 },309};310 311static struct kfd_gpu_cache_info vega20_cache_info[] = {312 {313 /* TCP L1 Cache per CU */314 .cache_size = 16,315 .cache_level = 1,316 .cache_line_size = 64,317 .flags = (CRAT_CACHE_FLAGS_ENABLED |318 CRAT_CACHE_FLAGS_DATA_CACHE |319 CRAT_CACHE_FLAGS_SIMD_CACHE),320 .num_cu_shared = 1,321 },322 {323 /* Scalar L1 Instruction Cache per SQC */324 .cache_size = 32,325 .cache_level = 1,326 .cache_line_size = 64,327 .flags = (CRAT_CACHE_FLAGS_ENABLED |328 CRAT_CACHE_FLAGS_INST_CACHE |329 CRAT_CACHE_FLAGS_SIMD_CACHE),330 .num_cu_shared = 3,331 },332 {333 /* Scalar L1 Data Cache per SQC */334 .cache_size = 16,335 .cache_level = 1,336 .cache_line_size = 64,337 .flags = (CRAT_CACHE_FLAGS_ENABLED |338 CRAT_CACHE_FLAGS_DATA_CACHE |339 CRAT_CACHE_FLAGS_SIMD_CACHE),340 .num_cu_shared = 3,341 },342 {343 /* L2 Data Cache per GPU (Total Tex Cache) */344 .cache_size = 8192,345 .cache_level = 2,346 .cache_line_size = 64,347 .flags = (CRAT_CACHE_FLAGS_ENABLED |348 CRAT_CACHE_FLAGS_DATA_CACHE |349 CRAT_CACHE_FLAGS_SIMD_CACHE),350 .num_cu_shared = 16,351 },352};353 354static struct kfd_gpu_cache_info aldebaran_cache_info[] = {355 {356 /* TCP L1 Cache per CU */357 .cache_size = 16,358 .cache_level = 1,359 .cache_line_size = 64,360 .flags = (CRAT_CACHE_FLAGS_ENABLED |361 CRAT_CACHE_FLAGS_DATA_CACHE |362 CRAT_CACHE_FLAGS_SIMD_CACHE),363 .num_cu_shared = 1,364 },365 {366 /* Scalar L1 Instruction Cache per SQC */367 .cache_size = 32,368 .cache_level = 1,369 .cache_line_size = 64,370 .flags = (CRAT_CACHE_FLAGS_ENABLED |371 CRAT_CACHE_FLAGS_INST_CACHE |372 CRAT_CACHE_FLAGS_SIMD_CACHE),373 .num_cu_shared = 2,374 },375 {376 /* Scalar L1 Data Cache per SQC */377 .cache_size = 16,378 .cache_level = 1,379 .cache_line_size = 64,380 .flags = (CRAT_CACHE_FLAGS_ENABLED |381 CRAT_CACHE_FLAGS_DATA_CACHE |382 CRAT_CACHE_FLAGS_SIMD_CACHE),383 .num_cu_shared = 2,384 },385 {386 /* L2 Data Cache per GPU (Total Tex Cache) */387 .cache_size = 8192,388 .cache_level = 2,389 .cache_line_size = 128,390 .flags = (CRAT_CACHE_FLAGS_ENABLED |391 CRAT_CACHE_FLAGS_DATA_CACHE |392 CRAT_CACHE_FLAGS_SIMD_CACHE),393 .num_cu_shared = 14,394 },395};396 397static struct kfd_gpu_cache_info navi10_cache_info[] = {398 {399 /* TCP L1 Cache per CU */400 .cache_size = 16,401 .cache_level = 1,402 .cache_line_size = 128,403 .flags = (CRAT_CACHE_FLAGS_ENABLED |404 CRAT_CACHE_FLAGS_DATA_CACHE |405 CRAT_CACHE_FLAGS_SIMD_CACHE),406 .num_cu_shared = 1,407 },408 {409 /* Scalar L1 Instruction Cache per SQC */410 .cache_size = 32,411 .cache_level = 1,412 .cache_line_size = 64,413 .flags = (CRAT_CACHE_FLAGS_ENABLED |414 CRAT_CACHE_FLAGS_INST_CACHE |415 CRAT_CACHE_FLAGS_SIMD_CACHE),416 .num_cu_shared = 2,417 },418 {419 /* Scalar L1 Data Cache per SQC */420 .cache_size = 16,421 .cache_level = 1,422 .cache_line_size = 64,423 .flags = (CRAT_CACHE_FLAGS_ENABLED |424 CRAT_CACHE_FLAGS_DATA_CACHE |425 CRAT_CACHE_FLAGS_SIMD_CACHE),426 .num_cu_shared = 2,427 },428 {429 /* GL1 Data Cache per SA */430 .cache_size = 128,431 .cache_level = 1,432 .cache_line_size = 128,433 .flags = (CRAT_CACHE_FLAGS_ENABLED |434 CRAT_CACHE_FLAGS_DATA_CACHE |435 CRAT_CACHE_FLAGS_SIMD_CACHE),436 .num_cu_shared = 10,437 },438 {439 /* L2 Data Cache per GPU (Total Tex Cache) */440 .cache_size = 4096,441 .cache_level = 2,442 .cache_line_size = 128,443 .flags = (CRAT_CACHE_FLAGS_ENABLED |444 CRAT_CACHE_FLAGS_DATA_CACHE |445 CRAT_CACHE_FLAGS_SIMD_CACHE),446 .num_cu_shared = 10,447 },448};449 450static struct kfd_gpu_cache_info vangogh_cache_info[] = {451 {452 /* TCP L1 Cache per CU */453 .cache_size = 16,454 .cache_level = 1,455 .cache_line_size = 128,456 .flags = (CRAT_CACHE_FLAGS_ENABLED |457 CRAT_CACHE_FLAGS_DATA_CACHE |458 CRAT_CACHE_FLAGS_SIMD_CACHE),459 .num_cu_shared = 1,460 },461 {462 /* Scalar L1 Instruction Cache per SQC */463 .cache_size = 32,464 .cache_level = 1,465 .cache_line_size = 64,466 .flags = (CRAT_CACHE_FLAGS_ENABLED |467 CRAT_CACHE_FLAGS_INST_CACHE |468 CRAT_CACHE_FLAGS_SIMD_CACHE),469 .num_cu_shared = 2,470 },471 {472 /* Scalar L1 Data Cache per SQC */473 .cache_size = 16,474 .cache_level = 1,475 .cache_line_size = 64,476 .flags = (CRAT_CACHE_FLAGS_ENABLED |477 CRAT_CACHE_FLAGS_DATA_CACHE |478 CRAT_CACHE_FLAGS_SIMD_CACHE),479 .num_cu_shared = 2,480 },481 {482 /* GL1 Data Cache per SA */483 .cache_size = 128,484 .cache_level = 1,485 .cache_line_size = 128,486 .flags = (CRAT_CACHE_FLAGS_ENABLED |487 CRAT_CACHE_FLAGS_DATA_CACHE |488 CRAT_CACHE_FLAGS_SIMD_CACHE),489 .num_cu_shared = 8,490 },491 {492 /* L2 Data Cache per GPU (Total Tex Cache) */493 .cache_size = 1024,494 .cache_level = 2,495 .cache_line_size = 128,496 .flags = (CRAT_CACHE_FLAGS_ENABLED |497 CRAT_CACHE_FLAGS_DATA_CACHE |498 CRAT_CACHE_FLAGS_SIMD_CACHE),499 .num_cu_shared = 8,500 },501};502 503static struct kfd_gpu_cache_info navi14_cache_info[] = {504 {505 /* TCP L1 Cache per CU */506 .cache_size = 16,507 .cache_level = 1,508 .cache_line_size = 128,509 .flags = (CRAT_CACHE_FLAGS_ENABLED |510 CRAT_CACHE_FLAGS_DATA_CACHE |511 CRAT_CACHE_FLAGS_SIMD_CACHE),512 .num_cu_shared = 1,513 },514 {515 /* Scalar L1 Instruction Cache per SQC */516 .cache_size = 32,517 .cache_level = 1,518 .cache_line_size = 64,519 .flags = (CRAT_CACHE_FLAGS_ENABLED |520 CRAT_CACHE_FLAGS_INST_CACHE |521 CRAT_CACHE_FLAGS_SIMD_CACHE),522 .num_cu_shared = 2,523 },524 {525 /* Scalar L1 Data Cache per SQC */526 .cache_size = 16,527 .cache_level = 1,528 .cache_line_size = 64,529 .flags = (CRAT_CACHE_FLAGS_ENABLED |530 CRAT_CACHE_FLAGS_DATA_CACHE |531 CRAT_CACHE_FLAGS_SIMD_CACHE),532 .num_cu_shared = 2,533 },534 {535 /* GL1 Data Cache per SA */536 .cache_size = 128,537 .cache_level = 1,538 .cache_line_size = 128,539 .flags = (CRAT_CACHE_FLAGS_ENABLED |540 CRAT_CACHE_FLAGS_DATA_CACHE |541 CRAT_CACHE_FLAGS_SIMD_CACHE),542 .num_cu_shared = 12,543 },544 {545 /* L2 Data Cache per GPU (Total Tex Cache) */546 .cache_size = 2048,547 .cache_level = 2,548 .cache_line_size = 128,549 .flags = (CRAT_CACHE_FLAGS_ENABLED |550 CRAT_CACHE_FLAGS_DATA_CACHE |551 CRAT_CACHE_FLAGS_SIMD_CACHE),552 .num_cu_shared = 12,553 },554};555 556static struct kfd_gpu_cache_info sienna_cichlid_cache_info[] = {557 {558 /* TCP L1 Cache per CU */559 .cache_size = 16,560 .cache_level = 1,561 .cache_line_size = 128,562 .flags = (CRAT_CACHE_FLAGS_ENABLED |563 CRAT_CACHE_FLAGS_DATA_CACHE |564 CRAT_CACHE_FLAGS_SIMD_CACHE),565 .num_cu_shared = 1,566 },567 {568 /* Scalar L1 Instruction Cache per SQC */569 .cache_size = 32,570 .cache_level = 1,571 .cache_line_size = 64,572 .flags = (CRAT_CACHE_FLAGS_ENABLED |573 CRAT_CACHE_FLAGS_INST_CACHE |574 CRAT_CACHE_FLAGS_SIMD_CACHE),575 .num_cu_shared = 2,576 },577 {578 /* Scalar L1 Data Cache per SQC */579 .cache_size = 16,580 .cache_level = 1,581 .cache_line_size = 64,582 .flags = (CRAT_CACHE_FLAGS_ENABLED |583 CRAT_CACHE_FLAGS_DATA_CACHE |584 CRAT_CACHE_FLAGS_SIMD_CACHE),585 .num_cu_shared = 2,586 },587 {588 /* GL1 Data Cache per SA */589 .cache_size = 128,590 .cache_level = 1,591 .cache_line_size = 128,592 .flags = (CRAT_CACHE_FLAGS_ENABLED |593 CRAT_CACHE_FLAGS_DATA_CACHE |594 CRAT_CACHE_FLAGS_SIMD_CACHE),595 .num_cu_shared = 10,596 },597 {598 /* L2 Data Cache per GPU (Total Tex Cache) */599 .cache_size = 4096,600 .cache_level = 2,601 .cache_line_size = 128,602 .flags = (CRAT_CACHE_FLAGS_ENABLED |603 CRAT_CACHE_FLAGS_DATA_CACHE |604 CRAT_CACHE_FLAGS_SIMD_CACHE),605 .num_cu_shared = 10,606 },607 {608 /* L3 Data Cache per GPU */609 .cache_size = 128*1024,610 .cache_level = 3,611 .cache_line_size = 64,612 .flags = (CRAT_CACHE_FLAGS_ENABLED |613 CRAT_CACHE_FLAGS_DATA_CACHE |614 CRAT_CACHE_FLAGS_SIMD_CACHE),615 .num_cu_shared = 10,616 },617};618 619static struct kfd_gpu_cache_info navy_flounder_cache_info[] = {620 {621 /* TCP L1 Cache per CU */622 .cache_size = 16,623 .cache_level = 1,624 .cache_line_size = 128,625 .flags = (CRAT_CACHE_FLAGS_ENABLED |626 CRAT_CACHE_FLAGS_DATA_CACHE |627 CRAT_CACHE_FLAGS_SIMD_CACHE),628 .num_cu_shared = 1,629 },630 {631 /* Scalar L1 Instruction Cache per SQC */632 .cache_size = 32,633 .cache_level = 1,634 .cache_line_size = 64,635 .flags = (CRAT_CACHE_FLAGS_ENABLED |636 CRAT_CACHE_FLAGS_INST_CACHE |637 CRAT_CACHE_FLAGS_SIMD_CACHE),638 .num_cu_shared = 2,639 },640 {641 /* Scalar L1 Data Cache per SQC */642 .cache_size = 16,643 .cache_level = 1,644 .cache_line_size = 64,645 .flags = (CRAT_CACHE_FLAGS_ENABLED |646 CRAT_CACHE_FLAGS_DATA_CACHE |647 CRAT_CACHE_FLAGS_SIMD_CACHE),648 .num_cu_shared = 2,649 },650 {651 /* GL1 Data Cache per SA */652 .cache_size = 128,653 .cache_level = 1,654 .cache_line_size = 128,655 .flags = (CRAT_CACHE_FLAGS_ENABLED |656 CRAT_CACHE_FLAGS_DATA_CACHE |657 CRAT_CACHE_FLAGS_SIMD_CACHE),658 .num_cu_shared = 10,659 },660 {661 /* L2 Data Cache per GPU (Total Tex Cache) */662 .cache_size = 3072,663 .cache_level = 2,664 .cache_line_size = 128,665 .flags = (CRAT_CACHE_FLAGS_ENABLED |666 CRAT_CACHE_FLAGS_DATA_CACHE |667 CRAT_CACHE_FLAGS_SIMD_CACHE),668 .num_cu_shared = 10,669 },670 {671 /* L3 Data Cache per GPU */672 .cache_size = 96*1024,673 .cache_level = 3,674 .cache_line_size = 64,675 .flags = (CRAT_CACHE_FLAGS_ENABLED |676 CRAT_CACHE_FLAGS_DATA_CACHE |677 CRAT_CACHE_FLAGS_SIMD_CACHE),678 .num_cu_shared = 10,679 },680};681 682static struct kfd_gpu_cache_info dimgrey_cavefish_cache_info[] = {683 {684 /* TCP L1 Cache per CU */685 .cache_size = 16,686 .cache_level = 1,687 .cache_line_size = 128,688 .flags = (CRAT_CACHE_FLAGS_ENABLED |689 CRAT_CACHE_FLAGS_DATA_CACHE |690 CRAT_CACHE_FLAGS_SIMD_CACHE),691 .num_cu_shared = 1,692 },693 {694 /* Scalar L1 Instruction Cache per SQC */695 .cache_size = 32,696 .cache_level = 1,697 .cache_line_size = 64,698 .flags = (CRAT_CACHE_FLAGS_ENABLED |699 CRAT_CACHE_FLAGS_INST_CACHE |700 CRAT_CACHE_FLAGS_SIMD_CACHE),701 .num_cu_shared = 2,702 },703 {704 /* Scalar L1 Data Cache per SQC */705 .cache_size = 16,706 .cache_level = 1,707 .cache_line_size = 64,708 .flags = (CRAT_CACHE_FLAGS_ENABLED |709 CRAT_CACHE_FLAGS_DATA_CACHE |710 CRAT_CACHE_FLAGS_SIMD_CACHE),711 .num_cu_shared = 2,712 },713 {714 /* GL1 Data Cache per SA */715 .cache_size = 128,716 .cache_level = 1,717 .cache_line_size = 128,718 .flags = (CRAT_CACHE_FLAGS_ENABLED |719 CRAT_CACHE_FLAGS_DATA_CACHE |720 CRAT_CACHE_FLAGS_SIMD_CACHE),721 .num_cu_shared = 8,722 },723 {724 /* L2 Data Cache per GPU (Total Tex Cache) */725 .cache_size = 2048,726 .cache_level = 2,727 .cache_line_size = 128,728 .flags = (CRAT_CACHE_FLAGS_ENABLED |729 CRAT_CACHE_FLAGS_DATA_CACHE |730 CRAT_CACHE_FLAGS_SIMD_CACHE),731 .num_cu_shared = 8,732 },733 {734 /* L3 Data Cache per GPU */735 .cache_size = 32*1024,736 .cache_level = 3,737 .cache_line_size = 64,738 .flags = (CRAT_CACHE_FLAGS_ENABLED |739 CRAT_CACHE_FLAGS_DATA_CACHE |740 CRAT_CACHE_FLAGS_SIMD_CACHE),741 .num_cu_shared = 8,742 },743};744 745static struct kfd_gpu_cache_info beige_goby_cache_info[] = {746 {747 /* TCP L1 Cache per CU */748 .cache_size = 16,749 .cache_level = 1,750 .cache_line_size = 128,751 .flags = (CRAT_CACHE_FLAGS_ENABLED |752 CRAT_CACHE_FLAGS_DATA_CACHE |753 CRAT_CACHE_FLAGS_SIMD_CACHE),754 .num_cu_shared = 1,755 },756 {757 /* Scalar L1 Instruction Cache per SQC */758 .cache_size = 32,759 .cache_level = 1,760 .cache_line_size = 64,761 .flags = (CRAT_CACHE_FLAGS_ENABLED |762 CRAT_CACHE_FLAGS_INST_CACHE |763 CRAT_CACHE_FLAGS_SIMD_CACHE),764 .num_cu_shared = 2,765 },766 {767 /* Scalar L1 Data Cache per SQC */768 .cache_size = 16,769 .cache_level = 1,770 .cache_line_size = 64,771 .flags = (CRAT_CACHE_FLAGS_ENABLED |772 CRAT_CACHE_FLAGS_DATA_CACHE |773 CRAT_CACHE_FLAGS_SIMD_CACHE),774 .num_cu_shared = 2,775 },776 {777 /* GL1 Data Cache per SA */778 .cache_size = 128,779 .cache_level = 1,780 .cache_line_size = 128,781 .flags = (CRAT_CACHE_FLAGS_ENABLED |782 CRAT_CACHE_FLAGS_DATA_CACHE |783 CRAT_CACHE_FLAGS_SIMD_CACHE),784 .num_cu_shared = 8,785 },786 {787 /* L2 Data Cache per GPU (Total Tex Cache) */788 .cache_size = 1024,789 .cache_level = 2,790 .cache_line_size = 128,791 .flags = (CRAT_CACHE_FLAGS_ENABLED |792 CRAT_CACHE_FLAGS_DATA_CACHE |793 CRAT_CACHE_FLAGS_SIMD_CACHE),794 .num_cu_shared = 8,795 },796 {797 /* L3 Data Cache per GPU */798 .cache_size = 16*1024,799 .cache_level = 3,800 .cache_line_size = 64,801 .flags = (CRAT_CACHE_FLAGS_ENABLED |802 CRAT_CACHE_FLAGS_DATA_CACHE |803 CRAT_CACHE_FLAGS_SIMD_CACHE),804 .num_cu_shared = 8,805 },806};807 808static struct kfd_gpu_cache_info yellow_carp_cache_info[] = {809 {810 /* TCP L1 Cache per CU */811 .cache_size = 16,812 .cache_level = 1,813 .cache_line_size = 128,814 .flags = (CRAT_CACHE_FLAGS_ENABLED |815 CRAT_CACHE_FLAGS_DATA_CACHE |816 CRAT_CACHE_FLAGS_SIMD_CACHE),817 .num_cu_shared = 1,818 },819 {820 /* Scalar L1 Instruction Cache per SQC */821 .cache_size = 32,822 .cache_level = 1,823 .cache_line_size = 64,824 .flags = (CRAT_CACHE_FLAGS_ENABLED |825 CRAT_CACHE_FLAGS_INST_CACHE |826 CRAT_CACHE_FLAGS_SIMD_CACHE),827 .num_cu_shared = 2,828 },829 {830 /* Scalar L1 Data Cache per SQC */831 .cache_size = 16,832 .cache_level = 1,833 .cache_line_size = 64,834 .flags = (CRAT_CACHE_FLAGS_ENABLED |835 CRAT_CACHE_FLAGS_DATA_CACHE |836 CRAT_CACHE_FLAGS_SIMD_CACHE),837 .num_cu_shared = 2,838 },839 {840 /* GL1 Data Cache per SA */841 .cache_size = 128,842 .cache_level = 1,843 .cache_line_size = 128,844 .flags = (CRAT_CACHE_FLAGS_ENABLED |845 CRAT_CACHE_FLAGS_DATA_CACHE |846 CRAT_CACHE_FLAGS_SIMD_CACHE),847 .num_cu_shared = 6,848 },849 {850 /* L2 Data Cache per GPU (Total Tex Cache) */851 .cache_size = 2048,852 .cache_level = 2,853 .cache_line_size = 128,854 .flags = (CRAT_CACHE_FLAGS_ENABLED |855 CRAT_CACHE_FLAGS_DATA_CACHE |856 CRAT_CACHE_FLAGS_SIMD_CACHE),857 .num_cu_shared = 6,858 },859};860 861static struct kfd_gpu_cache_info gfx1037_cache_info[] = {862 {863 /* TCP L1 Cache per CU */864 .cache_size = 16,865 .cache_level = 1,866 .cache_line_size = 128,867 .flags = (CRAT_CACHE_FLAGS_ENABLED |868 CRAT_CACHE_FLAGS_DATA_CACHE |869 CRAT_CACHE_FLAGS_SIMD_CACHE),870 .num_cu_shared = 1,871 },872 {873 /* Scalar L1 Instruction Cache per SQC */874 .cache_size = 32,875 .cache_level = 1,876 .cache_line_size = 64,877 .flags = (CRAT_CACHE_FLAGS_ENABLED |878 CRAT_CACHE_FLAGS_INST_CACHE |879 CRAT_CACHE_FLAGS_SIMD_CACHE),880 .num_cu_shared = 2,881 },882 {883 /* Scalar L1 Data Cache per SQC */884 .cache_size = 16,885 .cache_level = 1,886 .cache_line_size = 64,887 .flags = (CRAT_CACHE_FLAGS_ENABLED |888 CRAT_CACHE_FLAGS_DATA_CACHE |889 CRAT_CACHE_FLAGS_SIMD_CACHE),890 .num_cu_shared = 2,891 },892 {893 /* GL1 Data Cache per SA */894 .cache_size = 128,895 .cache_level = 1,896 .cache_line_size = 128,897 .flags = (CRAT_CACHE_FLAGS_ENABLED |898 CRAT_CACHE_FLAGS_DATA_CACHE |899 CRAT_CACHE_FLAGS_SIMD_CACHE),900 .num_cu_shared = 2,901 },902 {903 /* L2 Data Cache per GPU (Total Tex Cache) */904 .cache_size = 256,905 .cache_level = 2,906 .cache_line_size = 128,907 .flags = (CRAT_CACHE_FLAGS_ENABLED |908 CRAT_CACHE_FLAGS_DATA_CACHE |909 CRAT_CACHE_FLAGS_SIMD_CACHE),910 .num_cu_shared = 2,911 },912};913 914static struct kfd_gpu_cache_info gc_10_3_6_cache_info[] = {915 {916 /* TCP L1 Cache per CU */917 .cache_size = 16,918 .cache_level = 1,919 .cache_line_size = 128,920 .flags = (CRAT_CACHE_FLAGS_ENABLED |921 CRAT_CACHE_FLAGS_DATA_CACHE |922 CRAT_CACHE_FLAGS_SIMD_CACHE),923 .num_cu_shared = 1,924 },925 {926 /* Scalar L1 Instruction Cache per SQC */927 .cache_size = 32,928 .cache_level = 1,929 .cache_line_size = 64,930 .flags = (CRAT_CACHE_FLAGS_ENABLED |931 CRAT_CACHE_FLAGS_INST_CACHE |932 CRAT_CACHE_FLAGS_SIMD_CACHE),933 .num_cu_shared = 2,934 },935 {936 /* Scalar L1 Data Cache per SQC */937 .cache_size = 16,938 .cache_level = 1,939 .cache_line_size = 64,940 .flags = (CRAT_CACHE_FLAGS_ENABLED |941 CRAT_CACHE_FLAGS_DATA_CACHE |942 CRAT_CACHE_FLAGS_SIMD_CACHE),943 .num_cu_shared = 2,944 },945 {946 /* GL1 Data Cache per SA */947 .cache_size = 128,948 .cache_level = 1,949 .cache_line_size = 128,950 .flags = (CRAT_CACHE_FLAGS_ENABLED |951 CRAT_CACHE_FLAGS_DATA_CACHE |952 CRAT_CACHE_FLAGS_SIMD_CACHE),953 .num_cu_shared = 2,954 },955 {956 /* L2 Data Cache per GPU (Total Tex Cache) */957 .cache_size = 256,958 .cache_level = 2,959 .cache_line_size = 128,960 .flags = (CRAT_CACHE_FLAGS_ENABLED |961 CRAT_CACHE_FLAGS_DATA_CACHE |962 CRAT_CACHE_FLAGS_SIMD_CACHE),963 .num_cu_shared = 2,964 },965};966 967static struct kfd_gpu_cache_info dummy_cache_info[] = {968 {969 /* TCP L1 Cache per CU */970 .cache_size = 16,971 .cache_level = 1,972 .cache_line_size = 64,973 .flags = (CRAT_CACHE_FLAGS_ENABLED |974 CRAT_CACHE_FLAGS_DATA_CACHE |975 CRAT_CACHE_FLAGS_SIMD_CACHE),976 .num_cu_shared = 1,977 },978 {979 /* Scalar L1 Instruction Cache per SQC */980 .cache_size = 32,981 .cache_level = 1,982 .cache_line_size = 64,983 .flags = (CRAT_CACHE_FLAGS_ENABLED |984 CRAT_CACHE_FLAGS_INST_CACHE |985 CRAT_CACHE_FLAGS_SIMD_CACHE),986 .num_cu_shared = 2,987 },988 {989 /* Scalar L1 Data Cache per SQC */990 .cache_size = 16,991 .cache_level = 1,992 .cache_line_size = 64,993 .flags = (CRAT_CACHE_FLAGS_ENABLED |994 CRAT_CACHE_FLAGS_DATA_CACHE |995 CRAT_CACHE_FLAGS_SIMD_CACHE),996 .num_cu_shared = 2,997 },998 {999 /* GL1 Data Cache per SA */1000 .cache_size = 128,1001 .cache_level = 1,1002 .cache_line_size = 64,1003 .flags = (CRAT_CACHE_FLAGS_ENABLED |1004 CRAT_CACHE_FLAGS_DATA_CACHE |1005 CRAT_CACHE_FLAGS_SIMD_CACHE),1006 .num_cu_shared = 6,1007 },1008 {1009 /* L2 Data Cache per GPU (Total Tex Cache) */1010 .cache_size = 2048,1011 .cache_level = 2,1012 .cache_line_size = 64,1013 .flags = (CRAT_CACHE_FLAGS_ENABLED |1014 CRAT_CACHE_FLAGS_DATA_CACHE |1015 CRAT_CACHE_FLAGS_SIMD_CACHE),1016 .num_cu_shared = 6,1017 },1018};1019 1020static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev,1021 struct crat_subtype_computeunit *cu)1022{1023 dev->node_props.cpu_cores_count = cu->num_cpu_cores;1024 dev->node_props.cpu_core_id_base = cu->processor_id_low;1025 if (cu->hsa_capability & CRAT_CU_FLAGS_IOMMU_PRESENT)1026 dev->node_props.capability |= HSA_CAP_ATS_PRESENT;1027 1028 pr_debug("CU CPU: cores=%d id_base=%d\n", cu->num_cpu_cores,1029 cu->processor_id_low);1030}1031 1032static void kfd_populated_cu_info_gpu(struct kfd_topology_device *dev,1033 struct crat_subtype_computeunit *cu)1034{1035 dev->node_props.simd_id_base = cu->processor_id_low;1036 dev->node_props.simd_count = cu->num_simd_cores;1037 dev->node_props.lds_size_in_kb = cu->lds_size_in_kb;1038 dev->node_props.max_waves_per_simd = cu->max_waves_simd;1039 dev->node_props.wave_front_size = cu->wave_front_size;1040 dev->node_props.array_count = cu->array_count;1041 dev->node_props.cu_per_simd_array = cu->num_cu_per_array;1042 dev->node_props.simd_per_cu = cu->num_simd_per_cu;1043 dev->node_props.max_slots_scratch_cu = cu->max_slots_scatch_cu;1044 if (cu->hsa_capability & CRAT_CU_FLAGS_HOT_PLUGGABLE)1045 dev->node_props.capability |= HSA_CAP_HOT_PLUGGABLE;1046 pr_debug("CU GPU: id_base=%d\n", cu->processor_id_low);1047}1048 1049/* kfd_parse_subtype_cu - parse compute unit subtypes and attach it to correct1050 * topology device present in the device_list1051 */1052static int kfd_parse_subtype_cu(struct crat_subtype_computeunit *cu,1053 struct list_head *device_list)1054{1055 struct kfd_topology_device *dev;1056 1057 pr_debug("Found CU entry in CRAT table with proximity_domain=%d caps=%x\n",1058 cu->proximity_domain, cu->hsa_capability);1059 list_for_each_entry(dev, device_list, list) {1060 if (cu->proximity_domain == dev->proximity_domain) {1061 if (cu->flags & CRAT_CU_FLAGS_CPU_PRESENT)1062 kfd_populated_cu_info_cpu(dev, cu);1063 1064 if (cu->flags & CRAT_CU_FLAGS_GPU_PRESENT)1065 kfd_populated_cu_info_gpu(dev, cu);1066 break;1067 }1068 }1069 1070 return 0;1071}1072 1073static struct kfd_mem_properties *1074find_subtype_mem(uint32_t heap_type, uint32_t flags, uint32_t width,1075 struct kfd_topology_device *dev)1076{1077 struct kfd_mem_properties *props;1078 1079 list_for_each_entry(props, &dev->mem_props, list) {1080 if (props->heap_type == heap_type1081 && props->flags == flags1082 && props->width == width)1083 return props;1084 }1085 1086 return NULL;1087}1088/* kfd_parse_subtype_mem - parse memory subtypes and attach it to correct1089 * topology device present in the device_list1090 */1091static int kfd_parse_subtype_mem(struct crat_subtype_memory *mem,1092 struct list_head *device_list)1093{1094 struct kfd_mem_properties *props;1095 struct kfd_topology_device *dev;1096 uint32_t heap_type;1097 uint64_t size_in_bytes;1098 uint32_t flags = 0;1099 uint32_t width;1100 1101 pr_debug("Found memory entry in CRAT table with proximity_domain=%d\n",1102 mem->proximity_domain);1103 list_for_each_entry(dev, device_list, list) {1104 if (mem->proximity_domain == dev->proximity_domain) {1105 /* We're on GPU node */1106 if (dev->node_props.cpu_cores_count == 0) {1107 /* APU */1108 if (mem->visibility_type == 0)1109 heap_type =1110 HSA_MEM_HEAP_TYPE_FB_PRIVATE;1111 /* dGPU */1112 else1113 heap_type = mem->visibility_type;1114 } else1115 heap_type = HSA_MEM_HEAP_TYPE_SYSTEM;1116 1117 if (mem->flags & CRAT_MEM_FLAGS_HOT_PLUGGABLE)1118 flags |= HSA_MEM_FLAGS_HOT_PLUGGABLE;1119 if (mem->flags & CRAT_MEM_FLAGS_NON_VOLATILE)1120 flags |= HSA_MEM_FLAGS_NON_VOLATILE;1121 1122 size_in_bytes =1123 ((uint64_t)mem->length_high << 32) +1124 mem->length_low;1125 width = mem->width;1126 1127 /* Multiple banks of the same type are aggregated into1128 * one. User mode doesn't care about multiple physical1129 * memory segments. It's managed as a single virtual1130 * heap for user mode.1131 */1132 props = find_subtype_mem(heap_type, flags, width, dev);1133 if (props) {1134 props->size_in_bytes += size_in_bytes;1135 break;1136 }1137 1138 props = kfd_alloc_struct(props);1139 if (!props)1140 return -ENOMEM;1141 1142 props->heap_type = heap_type;1143 props->flags = flags;1144 props->size_in_bytes = size_in_bytes;1145 props->width = width;1146 1147 dev->node_props.mem_banks_count++;1148 list_add_tail(&props->list, &dev->mem_props);1149 1150 break;1151 }1152 }1153 1154 return 0;1155}1156 1157/* kfd_parse_subtype_cache - parse cache subtypes and attach it to correct1158 * topology device present in the device_list1159 */1160static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache,1161 struct list_head *device_list)1162{1163 struct kfd_cache_properties *props;1164 struct kfd_topology_device *dev;1165 uint32_t id;1166 uint32_t total_num_of_cu;1167 1168 id = cache->processor_id_low;1169 1170 pr_debug("Found cache entry in CRAT table with processor_id=%d\n", id);1171 list_for_each_entry(dev, device_list, list) {1172 total_num_of_cu = (dev->node_props.array_count *1173 dev->node_props.cu_per_simd_array);1174 1175 /* Cache infomration in CRAT doesn't have proximity_domain1176 * information as it is associated with a CPU core or GPU1177 * Compute Unit. So map the cache using CPU core Id or SIMD1178 * (GPU) ID.1179 * TODO: This works because currently we can safely assume that1180 * Compute Units are parsed before caches are parsed. In1181 * future, remove this dependency1182 */1183 if ((id >= dev->node_props.cpu_core_id_base &&1184 id <= dev->node_props.cpu_core_id_base +1185 dev->node_props.cpu_cores_count) ||1186 (id >= dev->node_props.simd_id_base &&1187 id < dev->node_props.simd_id_base +1188 total_num_of_cu)) {1189 props = kfd_alloc_struct(props);1190 if (!props)1191 return -ENOMEM;1192 1193 props->processor_id_low = id;1194 props->cache_level = cache->cache_level;1195 props->cache_size = cache->cache_size;1196 props->cacheline_size = cache->cache_line_size;1197 props->cachelines_per_tag = cache->lines_per_tag;1198 props->cache_assoc = cache->associativity;1199 props->cache_latency = cache->cache_latency;1200 1201 memcpy(props->sibling_map, cache->sibling_map,1202 CRAT_SIBLINGMAP_SIZE);1203 1204 /* set the sibling_map_size as 32 for CRAT from ACPI */1205 props->sibling_map_size = CRAT_SIBLINGMAP_SIZE;1206 1207 if (cache->flags & CRAT_CACHE_FLAGS_DATA_CACHE)1208 props->cache_type |= HSA_CACHE_TYPE_DATA;1209 if (cache->flags & CRAT_CACHE_FLAGS_INST_CACHE)1210 props->cache_type |= HSA_CACHE_TYPE_INSTRUCTION;1211 if (cache->flags & CRAT_CACHE_FLAGS_CPU_CACHE)1212 props->cache_type |= HSA_CACHE_TYPE_CPU;1213 if (cache->flags & CRAT_CACHE_FLAGS_SIMD_CACHE)1214 props->cache_type |= HSA_CACHE_TYPE_HSACU;1215 1216 dev->node_props.caches_count++;1217 list_add_tail(&props->list, &dev->cache_props);1218 1219 break;1220 }1221 }1222 1223 return 0;1224}1225 1226/* kfd_parse_subtype_iolink - parse iolink subtypes and attach it to correct1227 * topology device present in the device_list1228 */1229static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink,1230 struct list_head *device_list)1231{1232 struct kfd_iolink_properties *props = NULL, *props2;1233 struct kfd_topology_device *dev, *to_dev;1234 uint32_t id_from;1235 uint32_t id_to;1236 1237 id_from = iolink->proximity_domain_from;1238 id_to = iolink->proximity_domain_to;1239 1240 pr_debug("Found IO link entry in CRAT table with id_from=%d, id_to %d\n",1241 id_from, id_to);1242 list_for_each_entry(dev, device_list, list) {1243 if (id_from == dev->proximity_domain) {1244 props = kfd_alloc_struct(props);1245 if (!props)1246 return -ENOMEM;1247 1248 props->node_from = id_from;1249 props->node_to = id_to;1250 props->ver_maj = iolink->version_major;1251 props->ver_min = iolink->version_minor;1252 props->iolink_type = iolink->io_interface_type;1253 1254 if (props->iolink_type == CRAT_IOLINK_TYPE_PCIEXPRESS)1255 props->weight = 20;1256 else if (props->iolink_type == CRAT_IOLINK_TYPE_XGMI)1257 props->weight = iolink->weight_xgmi;1258 else1259 props->weight = node_distance(id_from, id_to);1260 1261 props->min_latency = iolink->minimum_latency;1262 props->max_latency = iolink->maximum_latency;1263 props->min_bandwidth = iolink->minimum_bandwidth_mbs;1264 props->max_bandwidth = iolink->maximum_bandwidth_mbs;1265 props->rec_transfer_size =1266 iolink->recommended_transfer_size;1267 1268 dev->node_props.io_links_count++;1269 list_add_tail(&props->list, &dev->io_link_props);1270 break;1271 }1272 }1273 1274 /* CPU topology is created before GPUs are detected, so CPU->GPU1275 * links are not built at that time. If a PCIe type is discovered, it1276 * means a GPU is detected and we are adding GPU->CPU to the topology.1277 * At this time, also add the corresponded CPU->GPU link if GPU1278 * is large bar.1279 * For xGMI, we only added the link with one direction in the crat1280 * table, add corresponded reversed direction link now.1281 */1282 if (props && (iolink->flags & CRAT_IOLINK_FLAGS_BI_DIRECTIONAL)) {1283 to_dev = kfd_topology_device_by_proximity_domain_no_lock(id_to);1284 if (!to_dev)1285 return -ENODEV;1286 /* same everything but the other direction */1287 props2 = kmemdup(props, sizeof(*props2), GFP_KERNEL);1288 if (!props2)1289 return -ENOMEM;1290 1291 props2->node_from = id_to;1292 props2->node_to = id_from;1293 props2->kobj = NULL;1294 to_dev->node_props.io_links_count++;1295 list_add_tail(&props2->list, &to_dev->io_link_props);1296 }1297 1298 return 0;1299}1300 1301/* kfd_parse_subtype - parse subtypes and attach it to correct topology device1302 * present in the device_list1303 * @sub_type_hdr - subtype section of crat_image1304 * @device_list - list of topology devices present in this crat_image1305 */1306static int kfd_parse_subtype(struct crat_subtype_generic *sub_type_hdr,1307 struct list_head *device_list)1308{1309 struct crat_subtype_computeunit *cu;1310 struct crat_subtype_memory *mem;1311 struct crat_subtype_cache *cache;1312 struct crat_subtype_iolink *iolink;1313 int ret = 0;1314 1315 switch (sub_type_hdr->type) {1316 case CRAT_SUBTYPE_COMPUTEUNIT_AFFINITY:1317 cu = (struct crat_subtype_computeunit *)sub_type_hdr;1318 ret = kfd_parse_subtype_cu(cu, device_list);1319 break;1320 case CRAT_SUBTYPE_MEMORY_AFFINITY:1321 mem = (struct crat_subtype_memory *)sub_type_hdr;1322 ret = kfd_parse_subtype_mem(mem, device_list);1323 break;1324 case CRAT_SUBTYPE_CACHE_AFFINITY:1325 cache = (struct crat_subtype_cache *)sub_type_hdr;1326 ret = kfd_parse_subtype_cache(cache, device_list);1327 break;1328 case CRAT_SUBTYPE_TLB_AFFINITY:1329 /*1330 * For now, nothing to do here1331 */1332 pr_debug("Found TLB entry in CRAT table (not processing)\n");1333 break;1334 case CRAT_SUBTYPE_CCOMPUTE_AFFINITY:1335 /*1336 * For now, nothing to do here1337 */1338 pr_debug("Found CCOMPUTE entry in CRAT table (not processing)\n");1339 break;1340 case CRAT_SUBTYPE_IOLINK_AFFINITY:1341 iolink = (struct crat_subtype_iolink *)sub_type_hdr;1342 ret = kfd_parse_subtype_iolink(iolink, device_list);1343 break;1344 default:1345 pr_warn("Unknown subtype %d in CRAT\n",1346 sub_type_hdr->type);1347 }1348 1349 return ret;1350}1351 1352/* kfd_parse_crat_table - parse CRAT table. For each node present in CRAT1353 * create a kfd_topology_device and add in to device_list. Also parse1354 * CRAT subtypes and attach it to appropriate kfd_topology_device1355 * @crat_image - input image containing CRAT1356 * @device_list - [OUT] list of kfd_topology_device generated after1357 * parsing crat_image1358 * @proximity_domain - Proximity domain of the first device in the table1359 *1360 * Return - 0 if successful else -ve value1361 */1362int kfd_parse_crat_table(void *crat_image, struct list_head *device_list,1363 uint32_t proximity_domain)1364{1365 struct kfd_topology_device *top_dev = NULL;1366 struct crat_subtype_generic *sub_type_hdr;1367 uint16_t node_id;1368 int ret = 0;1369 struct crat_header *crat_table = (struct crat_header *)crat_image;1370 uint16_t num_nodes;1371 uint32_t image_len;1372 1373 if (!crat_image)1374 return -EINVAL;1375 1376 if (!list_empty(device_list)) {1377 pr_warn("Error device list should be empty\n");1378 return -EINVAL;1379 }1380 1381 num_nodes = crat_table->num_domains;1382 image_len = crat_table->length;1383 1384 pr_debug("Parsing CRAT table with %d nodes\n", num_nodes);1385 1386 for (node_id = 0; node_id < num_nodes; node_id++) {1387 top_dev = kfd_create_topology_device(device_list);1388 if (!top_dev)1389 break;1390 top_dev->proximity_domain = proximity_domain++;1391 }1392 1393 if (!top_dev) {1394 ret = -ENOMEM;1395 goto err;1396 }1397 1398 memcpy(top_dev->oem_id, crat_table->oem_id, CRAT_OEMID_LENGTH);1399 memcpy(top_dev->oem_table_id, crat_table->oem_table_id,1400 CRAT_OEMTABLEID_LENGTH);1401 top_dev->oem_revision = crat_table->oem_revision;1402 1403 sub_type_hdr = (struct crat_subtype_generic *)(crat_table+1);1404 while ((char *)sub_type_hdr + sizeof(struct crat_subtype_generic) <1405 ((char *)crat_image) + image_len) {1406 if (sub_type_hdr->flags & CRAT_SUBTYPE_FLAGS_ENABLED) {1407 ret = kfd_parse_subtype(sub_type_hdr, device_list);1408 if (ret)1409 break;1410 }1411 1412 sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +1413 sub_type_hdr->length);1414 }1415 1416err:1417 if (ret)1418 kfd_release_topology_device_list(device_list);1419 1420 return ret;1421}1422 1423 1424static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,1425 struct kfd_gpu_cache_info *pcache_info)1426{1427 struct amdgpu_device *adev = kdev->adev;1428 int i = 0;1429 1430 /* TCP L1 Cache per CU */1431 if (adev->gfx.config.gc_tcp_l1_size) {1432 pcache_info[i].cache_size = adev->gfx.config.gc_tcp_l1_size;1433 pcache_info[i].cache_level = 1;1434 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1435 CRAT_CACHE_FLAGS_DATA_CACHE |1436 CRAT_CACHE_FLAGS_SIMD_CACHE);1437 pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_tcp_per_wpg / 2;1438 pcache_info[i].cache_line_size = adev->gfx.config.gc_tcp_cache_line_size;1439 i++;1440 }1441 /* Scalar L1 Instruction Cache per SQC */1442 if (adev->gfx.config.gc_l1_instruction_cache_size_per_sqc) {1443 pcache_info[i].cache_size =1444 adev->gfx.config.gc_l1_instruction_cache_size_per_sqc;1445 pcache_info[i].cache_level = 1;1446 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1447 CRAT_CACHE_FLAGS_INST_CACHE |1448 CRAT_CACHE_FLAGS_SIMD_CACHE);1449 pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_sqc_per_wgp * 2;1450 pcache_info[i].cache_line_size = adev->gfx.config.gc_instruction_cache_line_size;1451 i++;1452 }1453 /* Scalar L1 Data Cache per SQC */1454 if (adev->gfx.config.gc_l1_data_cache_size_per_sqc) {1455 pcache_info[i].cache_size = adev->gfx.config.gc_l1_data_cache_size_per_sqc;1456 pcache_info[i].cache_level = 1;1457 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1458 CRAT_CACHE_FLAGS_DATA_CACHE |1459 CRAT_CACHE_FLAGS_SIMD_CACHE);1460 pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_sqc_per_wgp * 2;1461 pcache_info[i].cache_line_size = adev->gfx.config.gc_scalar_data_cache_line_size;1462 i++;1463 }1464 /* GL1 Data Cache per SA */1465 if (adev->gfx.config.gc_gl1c_per_sa &&1466 adev->gfx.config.gc_gl1c_size_per_instance) {1467 pcache_info[i].cache_size = adev->gfx.config.gc_gl1c_per_sa *1468 adev->gfx.config.gc_gl1c_size_per_instance;1469 pcache_info[i].cache_level = 1;1470 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1471 CRAT_CACHE_FLAGS_DATA_CACHE |1472 CRAT_CACHE_FLAGS_SIMD_CACHE);1473 pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;1474 pcache_info[i].cache_line_size = 0;1475 i++;1476 }1477 /* L2 Data Cache per GPU (Total Tex Cache) */1478 if (adev->gfx.config.gc_gl2c_per_gpu) {1479 pcache_info[i].cache_size = adev->gfx.config.gc_gl2c_per_gpu;1480 pcache_info[i].cache_level = 2;1481 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1482 CRAT_CACHE_FLAGS_DATA_CACHE |1483 CRAT_CACHE_FLAGS_SIMD_CACHE);1484 pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;1485 pcache_info[i].cache_line_size = adev->gfx.config.gc_tcc_cache_line_size;1486 i++;1487 }1488 /* L3 Data Cache per GPU */1489 if (adev->gmc.mall_size) {1490 pcache_info[i].cache_size = adev->gmc.mall_size / 1024;1491 pcache_info[i].cache_level = 3;1492 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1493 CRAT_CACHE_FLAGS_DATA_CACHE |1494 CRAT_CACHE_FLAGS_SIMD_CACHE);1495 pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;1496 pcache_info[i].cache_line_size = 0;1497 i++;1498 }1499 return i;1500}1501 1502static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,1503 struct kfd_gpu_cache_info *pcache_info)1504{1505 struct amdgpu_device *adev = kdev->adev;1506 int i = 0;1507 1508 /* TCP L1 Cache per CU */1509 if (adev->gfx.config.gc_tcp_size_per_cu) {1510 pcache_info[i].cache_size = adev->gfx.config.gc_tcp_size_per_cu;1511 pcache_info[i].cache_level = 1;1512 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1513 CRAT_CACHE_FLAGS_DATA_CACHE |1514 CRAT_CACHE_FLAGS_SIMD_CACHE);1515 pcache_info[i].num_cu_shared = 1;1516 i++;1517 }1518 /* Scalar L1 Instruction Cache per SQC */1519 if (adev->gfx.config.gc_l1_instruction_cache_size_per_sqc) {1520 pcache_info[i].cache_size =1521 adev->gfx.config.gc_l1_instruction_cache_size_per_sqc;1522 pcache_info[i].cache_level = 1;1523 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1524 CRAT_CACHE_FLAGS_INST_CACHE |1525 CRAT_CACHE_FLAGS_SIMD_CACHE);1526 pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_cu_per_sqc;1527 i++;1528 }1529 /* Scalar L1 Data Cache per SQC */1530 if (adev->gfx.config.gc_l1_data_cache_size_per_sqc) {1531 pcache_info[i].cache_size = adev->gfx.config.gc_l1_data_cache_size_per_sqc;1532 pcache_info[i].cache_level = 1;1533 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1534 CRAT_CACHE_FLAGS_DATA_CACHE |1535 CRAT_CACHE_FLAGS_SIMD_CACHE);1536 pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_cu_per_sqc;1537 i++;1538 }1539 /* L2 Data Cache per GPU (Total Tex Cache) */1540 if (adev->gfx.config.gc_tcc_size) {1541 pcache_info[i].cache_size = adev->gfx.config.gc_tcc_size;1542 pcache_info[i].cache_level = 2;1543 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1544 CRAT_CACHE_FLAGS_DATA_CACHE |1545 CRAT_CACHE_FLAGS_SIMD_CACHE);1546 pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;1547 i++;1548 }1549 /* L3 Data Cache per GPU */1550 if (adev->gmc.mall_size) {1551 pcache_info[i].cache_size = adev->gmc.mall_size / 1024;1552 pcache_info[i].cache_level = 3;1553 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |1554 CRAT_CACHE_FLAGS_DATA_CACHE |1555 CRAT_CACHE_FLAGS_SIMD_CACHE);1556 pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;1557 i++;1558 }1559 return i;1560}1561 1562int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pcache_info)1563{1564 int num_of_cache_types = 0;1565 1566 switch (kdev->adev->asic_type) {1567 case CHIP_KAVERI:1568 *pcache_info = kaveri_cache_info;1569 num_of_cache_types = ARRAY_SIZE(kaveri_cache_info);1570 break;1571 case CHIP_HAWAII:1572 *pcache_info = hawaii_cache_info;1573 num_of_cache_types = ARRAY_SIZE(hawaii_cache_info);1574 break;1575 case CHIP_CARRIZO:1576 *pcache_info = carrizo_cache_info;1577 num_of_cache_types = ARRAY_SIZE(carrizo_cache_info);1578 break;1579 case CHIP_TONGA:1580 *pcache_info = tonga_cache_info;1581 num_of_cache_types = ARRAY_SIZE(tonga_cache_info);1582 break;1583 case CHIP_FIJI:1584 *pcache_info = fiji_cache_info;1585 num_of_cache_types = ARRAY_SIZE(fiji_cache_info);1586 break;1587 case CHIP_POLARIS10:1588 *pcache_info = polaris10_cache_info;1589 num_of_cache_types = ARRAY_SIZE(polaris10_cache_info);1590 break;1591 case CHIP_POLARIS11:1592 *pcache_info = polaris11_cache_info;1593 num_of_cache_types = ARRAY_SIZE(polaris11_cache_info);1594 break;1595 case CHIP_POLARIS12:1596 *pcache_info = polaris12_cache_info;1597 num_of_cache_types = ARRAY_SIZE(polaris12_cache_info);1598 break;1599 case CHIP_VEGAM:1600 *pcache_info = vegam_cache_info;1601 num_of_cache_types = ARRAY_SIZE(vegam_cache_info);1602 break;1603 default:1604 switch (KFD_GC_VERSION(kdev)) {1605 case IP_VERSION(9, 0, 1):1606 *pcache_info = vega10_cache_info;1607 num_of_cache_types = ARRAY_SIZE(vega10_cache_info);1608 break;1609 case IP_VERSION(9, 2, 1):1610 *pcache_info = vega12_cache_info;1611 num_of_cache_types = ARRAY_SIZE(vega12_cache_info);1612 break;1613 case IP_VERSION(9, 4, 0):1614 case IP_VERSION(9, 4, 1):1615 *pcache_info = vega20_cache_info;1616 num_of_cache_types = ARRAY_SIZE(vega20_cache_info);1617 break;1618 case IP_VERSION(9, 4, 2):1619 *pcache_info = aldebaran_cache_info;1620 num_of_cache_types = ARRAY_SIZE(aldebaran_cache_info);1621 break;1622 case IP_VERSION(9, 4, 3):1623 case IP_VERSION(9, 4, 4):1624 num_of_cache_types =1625 kfd_fill_gpu_cache_info_from_gfx_config_v2(kdev->kfd,1626 *pcache_info);1627 break;1628 case IP_VERSION(9, 1, 0):1629 case IP_VERSION(9, 2, 2):1630 *pcache_info = raven_cache_info;1631 num_of_cache_types = ARRAY_SIZE(raven_cache_info);1632 break;1633 case IP_VERSION(9, 3, 0):1634 *pcache_info = renoir_cache_info;1635 num_of_cache_types = ARRAY_SIZE(renoir_cache_info);1636 break;1637 case IP_VERSION(10, 1, 10):1638 case IP_VERSION(10, 1, 2):1639 case IP_VERSION(10, 1, 3):1640 case IP_VERSION(10, 1, 4):1641 *pcache_info = navi10_cache_info;1642 num_of_cache_types = ARRAY_SIZE(navi10_cache_info);1643 break;1644 case IP_VERSION(10, 1, 1):1645 *pcache_info = navi14_cache_info;1646 num_of_cache_types = ARRAY_SIZE(navi14_cache_info);1647 break;1648 case IP_VERSION(10, 3, 0):1649 *pcache_info = sienna_cichlid_cache_info;1650 num_of_cache_types = ARRAY_SIZE(sienna_cichlid_cache_info);1651 break;1652 case IP_VERSION(10, 3, 2):1653 *pcache_info = navy_flounder_cache_info;1654 num_of_cache_types = ARRAY_SIZE(navy_flounder_cache_info);1655 break;1656 case IP_VERSION(10, 3, 4):1657 *pcache_info = dimgrey_cavefish_cache_info;1658 num_of_cache_types = ARRAY_SIZE(dimgrey_cavefish_cache_info);1659 break;1660 case IP_VERSION(10, 3, 1):1661 *pcache_info = vangogh_cache_info;1662 num_of_cache_types = ARRAY_SIZE(vangogh_cache_info);1663 break;1664 case IP_VERSION(10, 3, 5):1665 *pcache_info = beige_goby_cache_info;1666 num_of_cache_types = ARRAY_SIZE(beige_goby_cache_info);1667 break;1668 case IP_VERSION(10, 3, 3):1669 *pcache_info = yellow_carp_cache_info;1670 num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info);1671 break;1672 case IP_VERSION(10, 3, 6):1673 *pcache_info = gc_10_3_6_cache_info;1674 num_of_cache_types = ARRAY_SIZE(gc_10_3_6_cache_info);1675 break;1676 case IP_VERSION(10, 3, 7):1677 *pcache_info = gfx1037_cache_info;1678 num_of_cache_types = ARRAY_SIZE(gfx1037_cache_info);1679 break;1680 case IP_VERSION(11, 0, 0):1681 case IP_VERSION(11, 0, 1):1682 case IP_VERSION(11, 0, 2):1683 case IP_VERSION(11, 0, 3):1684 case IP_VERSION(11, 0, 4):1685 case IP_VERSION(11, 5, 0):1686 case IP_VERSION(11, 5, 1):1687 case IP_VERSION(11, 5, 2):1688 case IP_VERSION(12, 0, 0):1689 case IP_VERSION(12, 0, 1):1690 num_of_cache_types =1691 kfd_fill_gpu_cache_info_from_gfx_config(kdev->kfd, *pcache_info);1692 break;1693 default:1694 *pcache_info = dummy_cache_info;1695 num_of_cache_types = ARRAY_SIZE(dummy_cache_info);1696 pr_warn("dummy cache info is used temporarily and real cache info need update later.\n");1697 break;1698 }1699 }1700 return num_of_cache_types;1701}1702 1703/* Memory required to create Virtual CRAT.1704 * Since there is no easy way to predict the amount of memory required, the1705 * following amount is allocated for GPU Virtual CRAT. This is1706 * expected to cover all known conditions. But to be safe additional check1707 * is put in the code to ensure we don't overwrite.1708 */1709#define VCRAT_SIZE_FOR_GPU (4 * PAGE_SIZE)1710 1711/* kfd_fill_cu_for_cpu - Fill in Compute info for the given CPU NUMA node1712 *1713 * @numa_node_id: CPU NUMA node id1714 * @avail_size: Available size in the memory1715 * @sub_type_hdr: Memory into which compute info will be filled in1716 *1717 * Return 0 if successful else return -ve value1718 */1719static int kfd_fill_cu_for_cpu(int numa_node_id, int *avail_size,1720 int proximity_domain,1721 struct crat_subtype_computeunit *sub_type_hdr)1722{1723 const struct cpumask *cpumask;1724 1725 *avail_size -= sizeof(struct crat_subtype_computeunit);1726 if (*avail_size < 0)1727 return -ENOMEM;1728 1729 memset(sub_type_hdr, 0, sizeof(struct crat_subtype_computeunit));1730 1731 /* Fill in subtype header data */1732 sub_type_hdr->type = CRAT_SUBTYPE_COMPUTEUNIT_AFFINITY;1733 sub_type_hdr->length = sizeof(struct crat_subtype_computeunit);1734 sub_type_hdr->flags = CRAT_SUBTYPE_FLAGS_ENABLED;1735 1736 cpumask = cpumask_of_node(numa_node_id);1737 1738 /* Fill in CU data */1739 sub_type_hdr->flags |= CRAT_CU_FLAGS_CPU_PRESENT;1740 sub_type_hdr->proximity_domain = proximity_domain;1741 sub_type_hdr->processor_id_low = kfd_numa_node_to_apic_id(numa_node_id);1742 if (sub_type_hdr->processor_id_low == -1)1743 return -EINVAL;1744 1745 sub_type_hdr->num_cpu_cores = cpumask_weight(cpumask);1746 1747 return 0;1748}1749 1750/* kfd_fill_mem_info_for_cpu - Fill in Memory info for the given CPU NUMA node1751 *1752 * @numa_node_id: CPU NUMA node id1753 * @avail_size: Available size in the memory1754 * @sub_type_hdr: Memory into which compute info will be filled in1755 *1756 * Return 0 if successful else return -ve value1757 */1758static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size,1759 int proximity_domain,1760 struct crat_subtype_memory *sub_type_hdr)1761{1762 uint64_t mem_in_bytes = 0;1763 pg_data_t *pgdat;1764 int zone_type;1765 1766 *avail_size -= sizeof(struct crat_subtype_memory);1767 if (*avail_size < 0)1768 return -ENOMEM;1769 1770 memset(sub_type_hdr, 0, sizeof(struct crat_subtype_memory));1771 1772 /* Fill in subtype header data */1773 sub_type_hdr->type = CRAT_SUBTYPE_MEMORY_AFFINITY;1774 sub_type_hdr->length = sizeof(struct crat_subtype_memory);1775 sub_type_hdr->flags = CRAT_SUBTYPE_FLAGS_ENABLED;1776 1777 /* Fill in Memory Subunit data */1778 1779 /* Unlike si_meminfo, si_meminfo_node is not exported. So1780 * the following lines are duplicated from si_meminfo_node1781 * function1782 */1783 pgdat = NODE_DATA(numa_node_id);1784 for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++)1785 mem_in_bytes += zone_managed_pages(&pgdat->node_zones[zone_type]);1786 mem_in_bytes <<= PAGE_SHIFT;1787 1788 sub_type_hdr->length_low = lower_32_bits(mem_in_bytes);1789 sub_type_hdr->length_high = upper_32_bits(mem_in_bytes);1790 sub_type_hdr->proximity_domain = proximity_domain;1791 1792 return 0;1793}1794 1795#ifdef CONFIG_X86_641796static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,1797 uint32_t *num_entries,1798 struct crat_subtype_iolink *sub_type_hdr)1799{1800 int nid;1801 struct cpuinfo_x86 *c = &cpu_data(0);1802 uint8_t link_type;1803 1804 if (c->x86_vendor == X86_VENDOR_AMD)1805 link_type = CRAT_IOLINK_TYPE_HYPERTRANSPORT;1806 else1807 link_type = CRAT_IOLINK_TYPE_QPI_1_1;1808 1809 *num_entries = 0;1810 1811 /* Create IO links from this node to other CPU nodes */1812 for_each_online_node(nid) {1813 if (nid == numa_node_id) /* node itself */1814 continue;1815 1816 *avail_size -= sizeof(struct crat_subtype_iolink);1817 if (*avail_size < 0)1818 return -ENOMEM;1819 1820 memset(sub_type_hdr, 0, sizeof(struct crat_subtype_iolink));1821 1822 /* Fill in subtype header data */1823 sub_type_hdr->type = CRAT_SUBTYPE_IOLINK_AFFINITY;1824 sub_type_hdr->length = sizeof(struct crat_subtype_iolink);1825 sub_type_hdr->flags = CRAT_SUBTYPE_FLAGS_ENABLED;1826 1827 /* Fill in IO link data */1828 sub_type_hdr->proximity_domain_from = numa_node_id;1829 sub_type_hdr->proximity_domain_to = nid;1830 sub_type_hdr->io_interface_type = link_type;1831 1832 (*num_entries)++;1833 sub_type_hdr++;1834 }1835 1836 return 0;1837}1838#endif1839 1840/* kfd_create_vcrat_image_cpu - Create Virtual CRAT for CPU1841 *1842 * @pcrat_image: Fill in VCRAT for CPU1843 * @size: [IN] allocated size of crat_image.1844 * [OUT] actual size of data filled in crat_image1845 */1846static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)1847{1848 struct crat_header *crat_table = (struct crat_header *)pcrat_image;1849 struct acpi_table_header *acpi_table;1850 acpi_status status;1851 struct crat_subtype_generic *sub_type_hdr;1852 int avail_size = *size;1853 int numa_node_id;1854#ifdef CONFIG_X86_641855 uint32_t entries = 0;1856#endif1857 int ret = 0;1858 1859 if (!pcrat_image)1860 return -EINVAL;1861 1862 /* Fill in CRAT Header.1863 * Modify length and total_entries as subunits are added.1864 */1865 avail_size -= sizeof(struct crat_header);1866 if (avail_size < 0)1867 return -ENOMEM;1868 1869 memset(crat_table, 0, sizeof(struct crat_header));1870 memcpy(&crat_table->signature, CRAT_SIGNATURE,1871 sizeof(crat_table->signature));1872 crat_table->length = sizeof(struct crat_header);1873 1874 status = acpi_get_table("DSDT", 0, &acpi_table);1875 if (status != AE_OK)1876 pr_warn("DSDT table not found for OEM information\n");1877 else {1878 crat_table->oem_revision = acpi_table->revision;1879 memcpy(crat_table->oem_id, acpi_table->oem_id,1880 CRAT_OEMID_LENGTH);1881 memcpy(crat_table->oem_table_id, acpi_table->oem_table_id,1882 CRAT_OEMTABLEID_LENGTH);1883 acpi_put_table(acpi_table);1884 }1885 crat_table->total_entries = 0;1886 crat_table->num_domains = 0;1887 1888 sub_type_hdr = (struct crat_subtype_generic *)(crat_table+1);1889 1890 for_each_online_node(numa_node_id) {1891 if (kfd_numa_node_to_apic_id(numa_node_id) == -1)1892 continue;1893 1894 /* Fill in Subtype: Compute Unit */1895 ret = kfd_fill_cu_for_cpu(numa_node_id, &avail_size,1896 crat_table->num_domains,1897 (struct crat_subtype_computeunit *)sub_type_hdr);1898 if (ret < 0)1899 return ret;1900 crat_table->length += sub_type_hdr->length;1901 crat_table->total_entries++;1902 1903 sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +1904 sub_type_hdr->length);1905 1906 /* Fill in Subtype: Memory */1907 ret = kfd_fill_mem_info_for_cpu(numa_node_id, &avail_size,1908 crat_table->num_domains,1909 (struct crat_subtype_memory *)sub_type_hdr);1910 if (ret < 0)1911 return ret;1912 crat_table->length += sub_type_hdr->length;1913 crat_table->total_entries++;1914 1915 sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +1916 sub_type_hdr->length);1917 1918 /* Fill in Subtype: IO Link */1919#ifdef CONFIG_X86_641920 ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size,1921 &entries,1922 (struct crat_subtype_iolink *)sub_type_hdr);1923 if (ret < 0)1924 return ret;1925 1926 if (entries) {1927 crat_table->length += (sub_type_hdr->length * entries);1928 crat_table->total_entries += entries;1929 1930 sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +1931 sub_type_hdr->length * entries);1932 }1933#else1934 pr_info("IO link not available for non x86 platforms\n");1935#endif1936 1937 crat_table->num_domains++;1938 }1939 1940 /* TODO: Add cache Subtype for CPU.1941 * Currently, CPU cache information is available in function1942 * detect_cache_attributes(cpu) defined in the file1943 * ./arch/x86/kernel/cpu/intel_cacheinfo.c. This function is not1944 * exported and to get the same information the code needs to be1945 * duplicated.1946 */1947 1948 *size = crat_table->length;1949 pr_info("Virtual CRAT table created for CPU\n");1950 1951 return 0;1952}1953 1954static int kfd_fill_gpu_memory_affinity(int *avail_size,1955 struct kfd_node *kdev, uint8_t type, uint64_t size,1956 struct crat_subtype_memory *sub_type_hdr,1957 uint32_t proximity_domain,1958 const struct kfd_local_mem_info *local_mem_info)1959{1960 *avail_size -= sizeof(struct crat_subtype_memory);1961 if (*avail_size < 0)1962 return -ENOMEM;1963 1964 memset((void *)sub_type_hdr, 0, sizeof(struct crat_subtype_memory));1965 sub_type_hdr->type = CRAT_SUBTYPE_MEMORY_AFFINITY;1966 sub_type_hdr->length = sizeof(struct crat_subtype_memory);1967 sub_type_hdr->flags |= CRAT_SUBTYPE_FLAGS_ENABLED;1968 1969 sub_type_hdr->proximity_domain = proximity_domain;1970 1971 pr_debug("Fill gpu memory affinity - type 0x%x size 0x%llx\n",1972 type, size);1973 1974 sub_type_hdr->length_low = lower_32_bits(size);1975 sub_type_hdr->length_high = upper_32_bits(size);1976 1977 sub_type_hdr->width = local_mem_info->vram_width;1978 sub_type_hdr->visibility_type = type;1979 1980 return 0;1981}1982 1983#ifdef CONFIG_ACPI_NUMA1984static void kfd_find_numa_node_in_srat(struct kfd_node *kdev)1985{1986 struct acpi_table_header *table_header = NULL;1987 struct acpi_subtable_header *sub_header = NULL;1988 unsigned long table_end, subtable_len;1989 u32 pci_id = pci_domain_nr(kdev->adev->pdev->bus) << 16 |1990 pci_dev_id(kdev->adev->pdev);1991 u32 bdf;1992 acpi_status status;1993 struct acpi_srat_cpu_affinity *cpu;1994 struct acpi_srat_generic_affinity *gpu;1995 int pxm = 0, max_pxm = 0;1996 int numa_node = NUMA_NO_NODE;1997 bool found = false;1998 1999 /* Fetch the SRAT table from ACPI */2000 status = acpi_get_table(ACPI_SIG_SRAT, 0, &table_header);2001 if (status == AE_NOT_FOUND) {2002 pr_warn("SRAT table not found\n");2003 return;2004 } else if (ACPI_FAILURE(status)) {2005 const char *err = acpi_format_exception(status);2006 pr_err("SRAT table error: %s\n", err);2007 return;2008 }2009 2010 table_end = (unsigned long)table_header + table_header->length;2011 2012 /* Parse all entries looking for a match. */2013 sub_header = (struct acpi_subtable_header *)2014 ((unsigned long)table_header +2015 sizeof(struct acpi_table_srat));2016 subtable_len = sub_header->length;2017 2018 while (((unsigned long)sub_header) + subtable_len < table_end) {2019 /*2020 * If length is 0, break from this loop to avoid2021 * infinite loop.2022 */2023 if (subtable_len == 0) {2024 pr_err("SRAT invalid zero length\n");2025 break;2026 }2027 2028 switch (sub_header->type) {2029 case ACPI_SRAT_TYPE_CPU_AFFINITY:2030 cpu = (struct acpi_srat_cpu_affinity *)sub_header;2031 pxm = *((u32 *)cpu->proximity_domain_hi) << 8 |2032 cpu->proximity_domain_lo;2033 if (pxm > max_pxm)2034 max_pxm = pxm;2035 break;2036 case ACPI_SRAT_TYPE_GENERIC_AFFINITY:2037 gpu = (struct acpi_srat_generic_affinity *)sub_header;2038 bdf = *((u16 *)(&gpu->device_handle[0])) << 16 |2039 *((u16 *)(&gpu->device_handle[2]));2040 if (bdf == pci_id) {2041 found = true;2042 numa_node = pxm_to_node(gpu->proximity_domain);2043 }2044 break;2045 default:2046 break;2047 }2048 2049 if (found)2050 break;2051 2052 sub_header = (struct acpi_subtable_header *)2053 ((unsigned long)sub_header + subtable_len);2054 subtable_len = sub_header->length;2055 }2056 2057 acpi_put_table(table_header);2058 2059 /* Workaround bad cpu-gpu binding case */2060 if (found && (numa_node < 0 ||2061 numa_node > pxm_to_node(max_pxm)))2062 numa_node = 0;2063 2064 if (numa_node != NUMA_NO_NODE)2065 set_dev_node(&kdev->adev->pdev->dev, numa_node);2066}2067#endif2068 2069#define KFD_CRAT_INTRA_SOCKET_WEIGHT 132070#define KFD_CRAT_XGMI_WEIGHT 152071 2072/* kfd_fill_gpu_direct_io_link - Fill in direct io link from GPU2073 * to its NUMA node2074 * @avail_size: Available size in the memory2075 * @kdev - [IN] GPU device2076 * @sub_type_hdr: Memory into which io link info will be filled in2077 * @proximity_domain - proximity domain of the GPU node2078 *2079 * Return 0 if successful else return -ve value2080 */2081static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size,2082 struct kfd_node *kdev,2083 struct crat_subtype_iolink *sub_type_hdr,2084 uint32_t proximity_domain)2085{2086 *avail_size -= sizeof(struct crat_subtype_iolink);2087 if (*avail_size < 0)2088 return -ENOMEM;2089 2090 memset((void *)sub_type_hdr, 0, sizeof(struct crat_subtype_iolink));2091 2092 /* Fill in subtype header data */2093 sub_type_hdr->type = CRAT_SUBTYPE_IOLINK_AFFINITY;2094 sub_type_hdr->length = sizeof(struct crat_subtype_iolink);2095 sub_type_hdr->flags |= CRAT_SUBTYPE_FLAGS_ENABLED;2096 if (kfd_dev_is_large_bar(kdev))2097 sub_type_hdr->flags |= CRAT_IOLINK_FLAGS_BI_DIRECTIONAL;2098 2099 /* Fill in IOLINK subtype.2100 * TODO: Fill-in other fields of iolink subtype2101 */2102 if (kdev->adev->gmc.xgmi.connected_to_cpu ||2103 (KFD_GC_VERSION(kdev) == IP_VERSION(9, 4, 3) &&2104 kdev->adev->smuio.funcs->get_pkg_type(kdev->adev) ==2105 AMDGPU_PKG_TYPE_APU)) {2106 bool ext_cpu = KFD_GC_VERSION(kdev) != IP_VERSION(9, 4, 3);2107 int mem_bw = 819200, weight = ext_cpu ? KFD_CRAT_XGMI_WEIGHT :2108 KFD_CRAT_INTRA_SOCKET_WEIGHT;2109 uint32_t bandwidth = ext_cpu ? amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(2110 kdev->adev, NULL, true) : mem_bw;2111 2112 /*2113 * with host gpu xgmi link, host can access gpu memory whether2114 * or not pcie bar type is large, so always create bidirectional2115 * io link.2116 */2117 sub_type_hdr->flags |= CRAT_IOLINK_FLAGS_BI_DIRECTIONAL;2118 sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI;2119 sub_type_hdr->weight_xgmi = weight;2120 sub_type_hdr->minimum_bandwidth_mbs = bandwidth;2121 sub_type_hdr->maximum_bandwidth_mbs = bandwidth;2122 } else {2123 sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_PCIEXPRESS;2124 sub_type_hdr->minimum_bandwidth_mbs =2125 amdgpu_amdkfd_get_pcie_bandwidth_mbytes(kdev->adev, true);2126 sub_type_hdr->maximum_bandwidth_mbs =2127 amdgpu_amdkfd_get_pcie_bandwidth_mbytes(kdev->adev, false);2128 }2129 2130 sub_type_hdr->proximity_domain_from = proximity_domain;2131 2132#ifdef CONFIG_ACPI_NUMA2133 if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE &&2134 num_possible_nodes() > 1)2135 kfd_find_numa_node_in_srat(kdev);2136#endif2137#ifdef CONFIG_NUMA2138 if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE)2139 sub_type_hdr->proximity_domain_to = 0;2140 else2141 sub_type_hdr->proximity_domain_to = kdev->adev->pdev->dev.numa_node;2142#else2143 sub_type_hdr->proximity_domain_to = 0;2144#endif2145 return 0;2146}2147 2148static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size,2149 struct kfd_node *kdev,2150 struct kfd_node *peer_kdev,2151 struct crat_subtype_iolink *sub_type_hdr,2152 uint32_t proximity_domain_from,2153 uint32_t proximity_domain_to)2154{2155 bool use_ta_info = kdev->kfd->num_nodes == 1;2156 2157 *avail_size -= sizeof(struct crat_subtype_iolink);2158 if (*avail_size < 0)2159 return -ENOMEM;2160 2161 memset((void *)sub_type_hdr, 0, sizeof(struct crat_subtype_iolink));2162 2163 sub_type_hdr->type = CRAT_SUBTYPE_IOLINK_AFFINITY;2164 sub_type_hdr->length = sizeof(struct crat_subtype_iolink);2165 sub_type_hdr->flags |= CRAT_SUBTYPE_FLAGS_ENABLED |2166 CRAT_IOLINK_FLAGS_BI_DIRECTIONAL;2167 2168 sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI;2169 sub_type_hdr->proximity_domain_from = proximity_domain_from;2170 sub_type_hdr->proximity_domain_to = proximity_domain_to;2171 2172 if (use_ta_info) {2173 sub_type_hdr->weight_xgmi = KFD_CRAT_XGMI_WEIGHT *2174 amdgpu_amdkfd_get_xgmi_hops_count(kdev->adev, peer_kdev->adev);2175 sub_type_hdr->maximum_bandwidth_mbs =2176 amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->adev,2177 peer_kdev->adev, false);2178 sub_type_hdr->minimum_bandwidth_mbs = sub_type_hdr->maximum_bandwidth_mbs ?2179 amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->adev, NULL, true) : 0;2180 } else {2181 bool is_single_hop = kdev->kfd == peer_kdev->kfd;2182 int weight = is_single_hop ? KFD_CRAT_INTRA_SOCKET_WEIGHT :2183 (2 * KFD_CRAT_INTRA_SOCKET_WEIGHT) + KFD_CRAT_XGMI_WEIGHT;2184 int mem_bw = 819200;2185 2186 sub_type_hdr->weight_xgmi = weight;2187 sub_type_hdr->maximum_bandwidth_mbs = is_single_hop ? mem_bw : 0;2188 sub_type_hdr->minimum_bandwidth_mbs = is_single_hop ? mem_bw : 0;2189 }2190 2191 return 0;2192}2193 2194/* kfd_create_vcrat_image_gpu - Create Virtual CRAT for CPU2195 *2196 * @pcrat_image: Fill in VCRAT for GPU2197 * @size: [IN] allocated size of crat_image.2198 * [OUT] actual size of data filled in crat_image2199 */2200static int kfd_create_vcrat_image_gpu(void *pcrat_image,2201 size_t *size, struct kfd_node *kdev,2202 uint32_t proximity_domain)2203{2204 struct crat_header *crat_table = (struct crat_header *)pcrat_image;2205 struct amdgpu_gfx_config *gfx_info = &kdev->adev->gfx.config;2206 struct amdgpu_cu_info *cu_info = &kdev->adev->gfx.cu_info;2207 struct crat_subtype_generic *sub_type_hdr;2208 struct kfd_local_mem_info local_mem_info;2209 struct kfd_topology_device *peer_dev;2210 struct crat_subtype_computeunit *cu;2211 int avail_size = *size;2212 uint32_t total_num_of_cu;2213 uint32_t nid = 0;2214 int ret = 0;2215 2216 if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_GPU)2217 return -EINVAL;2218 2219 /* Fill the CRAT Header.2220 * Modify length and total_entries as subunits are added.2221 */2222 avail_size -= sizeof(struct crat_header);2223 memset(crat_table, 0, sizeof(struct crat_header));2224 2225 memcpy(&crat_table->signature, CRAT_SIGNATURE,2226 sizeof(crat_table->signature));2227 /* Change length as we add more subtypes*/2228 crat_table->length = sizeof(struct crat_header);2229 crat_table->num_domains = 1;2230 crat_table->total_entries = 0;2231 2232 /* Fill in Subtype: Compute Unit2233 * First fill in the sub type header and then sub type data2234 */2235 avail_size -= sizeof(struct crat_subtype_computeunit);2236 sub_type_hdr = (struct crat_subtype_generic *)(crat_table + 1);2237 memset(sub_type_hdr, 0, sizeof(struct crat_subtype_computeunit));2238 2239 sub_type_hdr->type = CRAT_SUBTYPE_COMPUTEUNIT_AFFINITY;2240 sub_type_hdr->length = sizeof(struct crat_subtype_computeunit);2241 sub_type_hdr->flags = CRAT_SUBTYPE_FLAGS_ENABLED;2242 2243 /* Fill CU subtype data */2244 cu = (struct crat_subtype_computeunit *)sub_type_hdr;2245 cu->flags |= CRAT_CU_FLAGS_GPU_PRESENT;2246 cu->proximity_domain = proximity_domain;2247 2248 cu->num_simd_per_cu = cu_info->simd_per_cu;2249 cu->num_simd_cores = cu_info->simd_per_cu *2250 (cu_info->number / kdev->kfd->num_nodes);2251 cu->max_waves_simd = cu_info->max_waves_per_simd;2252 2253 cu->wave_front_size = cu_info->wave_front_size;2254 cu->array_count = gfx_info->max_sh_per_se *2255 gfx_info->max_shader_engines;2256 total_num_of_cu = (cu->array_count * gfx_info->max_cu_per_sh);2257 cu->processor_id_low = get_and_inc_gpu_processor_id(total_num_of_cu);2258 cu->num_cu_per_array = gfx_info->max_cu_per_sh;2259 cu->max_slots_scatch_cu = cu_info->max_scratch_slots_per_cu;2260 cu->num_banks = gfx_info->max_shader_engines;2261 cu->lds_size_in_kb = cu_info->lds_size;2262 2263 cu->hsa_capability = 0;2264 2265 crat_table->length += sub_type_hdr->length;2266 crat_table->total_entries++;2267 2268 /* Fill in Subtype: Memory. Only on systems with large BAR (no2269 * private FB), report memory as public. On other systems2270 * report the total FB size (public+private) as a single2271 * private heap.2272 */2273 local_mem_info = kdev->local_mem_info;2274 sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +2275 sub_type_hdr->length);2276 2277 if (kdev->adev->debug_largebar)2278 local_mem_info.local_mem_size_private = 0;2279 2280 if (local_mem_info.local_mem_size_private == 0)2281 ret = kfd_fill_gpu_memory_affinity(&avail_size,2282 kdev, HSA_MEM_HEAP_TYPE_FB_PUBLIC,2283 local_mem_info.local_mem_size_public,2284 (struct crat_subtype_memory *)sub_type_hdr,2285 proximity_domain,2286 &local_mem_info);2287 else2288 ret = kfd_fill_gpu_memory_affinity(&avail_size,2289 kdev, HSA_MEM_HEAP_TYPE_FB_PRIVATE,2290 local_mem_info.local_mem_size_public +2291 local_mem_info.local_mem_size_private,2292 (struct crat_subtype_memory *)sub_type_hdr,2293 proximity_domain,2294 &local_mem_info);2295 if (ret < 0)2296 return ret;2297 2298 crat_table->length += sizeof(struct crat_subtype_memory);2299 crat_table->total_entries++;2300 2301 /* Fill in Subtype: IO_LINKS2302 * Only direct links are added here which is Link from GPU to2303 * its NUMA node. Indirect links are added by userspace.2304 */2305 sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +2306 sub_type_hdr->length);2307 ret = kfd_fill_gpu_direct_io_link_to_cpu(&avail_size, kdev,2308 (struct crat_subtype_iolink *)sub_type_hdr, proximity_domain);2309 2310 if (ret < 0)2311 return ret;2312 2313 crat_table->length += sub_type_hdr->length;2314 crat_table->total_entries++;2315 2316 2317 /* Fill in Subtype: IO_LINKS2318 * Direct links from GPU to other GPUs through xGMI.2319 * We will loop GPUs that already be processed (with lower value2320 * of proximity_domain), add the link for the GPUs with same2321 * hive id (from this GPU to other GPU) . The reversed iolink2322 * (from other GPU to this GPU) will be added2323 * in kfd_parse_subtype_iolink.2324 */2325 if (kdev->kfd->hive_id) {2326 for (nid = 0; nid < proximity_domain; ++nid) {2327 peer_dev = kfd_topology_device_by_proximity_domain_no_lock(nid);2328 if (!peer_dev->gpu)2329 continue;2330 if (peer_dev->gpu->kfd->hive_id != kdev->kfd->hive_id)2331 continue;2332 sub_type_hdr = (typeof(sub_type_hdr))(2333 (char *)sub_type_hdr +2334 sizeof(struct crat_subtype_iolink));2335 ret = kfd_fill_gpu_xgmi_link_to_gpu(2336 &avail_size, kdev, peer_dev->gpu,2337 (struct crat_subtype_iolink *)sub_type_hdr,2338 proximity_domain, nid);2339 if (ret < 0)2340 return ret;2341 crat_table->length += sub_type_hdr->length;2342 crat_table->total_entries++;2343 }2344 }2345 *size = crat_table->length;2346 pr_info("Virtual CRAT table created for GPU\n");2347 2348 return ret;2349}2350 2351/* kfd_create_crat_image_virtual - Allocates memory for CRAT image and2352 * creates a Virtual CRAT (VCRAT) image2353 *2354 * NOTE: Call kfd_destroy_crat_image to free CRAT image memory2355 *2356 * @crat_image: VCRAT image created because ACPI does not have a2357 * CRAT for this device2358 * @size: [OUT] size of virtual crat_image2359 * @flags: COMPUTE_UNIT_CPU - Create VCRAT for CPU device2360 * COMPUTE_UNIT_GPU - Create VCRAT for GPU2361 * (COMPUTE_UNIT_CPU | COMPUTE_UNIT_GPU) - Create VCRAT for APU2362 * -- this option is not currently implemented.2363 * The assumption is that all AMD APUs will have CRAT2364 * @kdev: Valid kfd_node required if flags contain COMPUTE_UNIT_GPU2365 *2366 * Return 0 if successful else return -ve value2367 */2368int kfd_create_crat_image_virtual(void **crat_image, size_t *size,2369 int flags, struct kfd_node *kdev,2370 uint32_t proximity_domain)2371{2372 void *pcrat_image = NULL;2373 int ret = 0, num_nodes;2374 size_t dyn_size;2375 2376 if (!crat_image)2377 return -EINVAL;2378 2379 *crat_image = NULL;2380 2381 /* Allocate the CPU Virtual CRAT size based on the number of online2382 * nodes. Allocate VCRAT_SIZE_FOR_GPU for GPU virtual CRAT image.2383 * This should cover all the current conditions. A check is put not2384 * to overwrite beyond allocated size for GPUs2385 */2386 switch (flags) {2387 case COMPUTE_UNIT_CPU:2388 num_nodes = num_online_nodes();2389 dyn_size = sizeof(struct crat_header) +2390 num_nodes * (sizeof(struct crat_subtype_computeunit) +2391 sizeof(struct crat_subtype_memory) +2392 (num_nodes - 1) * sizeof(struct crat_subtype_iolink));2393 pcrat_image = kvmalloc(dyn_size, GFP_KERNEL);2394 if (!pcrat_image)2395 return -ENOMEM;2396 *size = dyn_size;2397 pr_debug("CRAT size is %ld", dyn_size);2398 ret = kfd_create_vcrat_image_cpu(pcrat_image, size);2399 break;2400 case COMPUTE_UNIT_GPU:2401 if (!kdev)2402 return -EINVAL;2403 pcrat_image = kvmalloc(VCRAT_SIZE_FOR_GPU, GFP_KERNEL);2404 if (!pcrat_image)2405 return -ENOMEM;2406 *size = VCRAT_SIZE_FOR_GPU;2407 ret = kfd_create_vcrat_image_gpu(pcrat_image, size, kdev,2408 proximity_domain);2409 break;2410 case (COMPUTE_UNIT_CPU | COMPUTE_UNIT_GPU):2411 /* TODO: */2412 ret = -EINVAL;2413 pr_err("VCRAT not implemented for APU\n");2414 break;2415 default:2416 ret = -EINVAL;2417 }2418 2419 if (!ret)2420 *crat_image = pcrat_image;2421 else2422 kvfree(pcrat_image);2423 2424 return ret;2425}2426 2427 2428/* kfd_destroy_crat_image2429 *2430 * @crat_image: [IN] - crat_image from kfd_create_crat_image_xxx(..)2431 *2432 */2433void kfd_destroy_crat_image(void *crat_image)2434{2435 kvfree(crat_image);2436}2437