brintos

brintos / linux-shallow public Read only

0
0
Text · 68.2 KiB · 48caecf Raw
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