18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2014 Advanced Micro Devices, Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
128c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software.
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
158c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
168c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
178c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
188c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
198c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
208c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
218c2ecf20Sopenharmony_ci */
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include <linux/bsearch.h>
248c2ecf20Sopenharmony_ci#include <linux/pci.h>
258c2ecf20Sopenharmony_ci#include <linux/slab.h>
268c2ecf20Sopenharmony_ci#include "kfd_priv.h"
278c2ecf20Sopenharmony_ci#include "kfd_device_queue_manager.h"
288c2ecf20Sopenharmony_ci#include "kfd_pm4_headers_vi.h"
298c2ecf20Sopenharmony_ci#include "cwsr_trap_handler.h"
308c2ecf20Sopenharmony_ci#include "kfd_iommu.h"
318c2ecf20Sopenharmony_ci#include "amdgpu_amdkfd.h"
328c2ecf20Sopenharmony_ci#include "kfd_smi_events.h"
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define MQD_SIZE_ALIGNED 768
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/*
378c2ecf20Sopenharmony_ci * kfd_locked is used to lock the kfd driver during suspend or reset
388c2ecf20Sopenharmony_ci * once locked, kfd driver will stop any further GPU execution.
398c2ecf20Sopenharmony_ci * create process (open) will return -EAGAIN.
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_cistatic atomic_t kfd_locked = ATOMIC_INIT(0);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#ifdef CONFIG_DRM_AMDGPU_CIK
448c2ecf20Sopenharmony_ciextern const struct kfd2kgd_calls gfx_v7_kfd2kgd;
458c2ecf20Sopenharmony_ci#endif
468c2ecf20Sopenharmony_ciextern const struct kfd2kgd_calls gfx_v8_kfd2kgd;
478c2ecf20Sopenharmony_ciextern const struct kfd2kgd_calls gfx_v9_kfd2kgd;
488c2ecf20Sopenharmony_ciextern const struct kfd2kgd_calls arcturus_kfd2kgd;
498c2ecf20Sopenharmony_ciextern const struct kfd2kgd_calls gfx_v10_kfd2kgd;
508c2ecf20Sopenharmony_ciextern const struct kfd2kgd_calls gfx_v10_3_kfd2kgd;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic const struct kfd2kgd_calls *kfd2kgd_funcs[] = {
538c2ecf20Sopenharmony_ci#ifdef KFD_SUPPORT_IOMMU_V2
548c2ecf20Sopenharmony_ci#ifdef CONFIG_DRM_AMDGPU_CIK
558c2ecf20Sopenharmony_ci	[CHIP_KAVERI] = &gfx_v7_kfd2kgd,
568c2ecf20Sopenharmony_ci#endif
578c2ecf20Sopenharmony_ci	[CHIP_CARRIZO] = &gfx_v8_kfd2kgd,
588c2ecf20Sopenharmony_ci	[CHIP_RAVEN] = &gfx_v9_kfd2kgd,
598c2ecf20Sopenharmony_ci#endif
608c2ecf20Sopenharmony_ci#ifdef CONFIG_DRM_AMDGPU_CIK
618c2ecf20Sopenharmony_ci	[CHIP_HAWAII] = &gfx_v7_kfd2kgd,
628c2ecf20Sopenharmony_ci#endif
638c2ecf20Sopenharmony_ci	[CHIP_TONGA] = &gfx_v8_kfd2kgd,
648c2ecf20Sopenharmony_ci	[CHIP_FIJI] = &gfx_v8_kfd2kgd,
658c2ecf20Sopenharmony_ci	[CHIP_POLARIS10] = &gfx_v8_kfd2kgd,
668c2ecf20Sopenharmony_ci	[CHIP_POLARIS11] = &gfx_v8_kfd2kgd,
678c2ecf20Sopenharmony_ci	[CHIP_POLARIS12] = &gfx_v8_kfd2kgd,
688c2ecf20Sopenharmony_ci	[CHIP_VEGAM] = &gfx_v8_kfd2kgd,
698c2ecf20Sopenharmony_ci	[CHIP_VEGA10] = &gfx_v9_kfd2kgd,
708c2ecf20Sopenharmony_ci	[CHIP_VEGA12] = &gfx_v9_kfd2kgd,
718c2ecf20Sopenharmony_ci	[CHIP_VEGA20] = &gfx_v9_kfd2kgd,
728c2ecf20Sopenharmony_ci	[CHIP_RENOIR] = &gfx_v9_kfd2kgd,
738c2ecf20Sopenharmony_ci	[CHIP_ARCTURUS] = &arcturus_kfd2kgd,
748c2ecf20Sopenharmony_ci	[CHIP_NAVI10] = &gfx_v10_kfd2kgd,
758c2ecf20Sopenharmony_ci	[CHIP_NAVI12] = &gfx_v10_kfd2kgd,
768c2ecf20Sopenharmony_ci	[CHIP_NAVI14] = &gfx_v10_kfd2kgd,
778c2ecf20Sopenharmony_ci	[CHIP_SIENNA_CICHLID] = &gfx_v10_3_kfd2kgd,
788c2ecf20Sopenharmony_ci	[CHIP_NAVY_FLOUNDER] = &gfx_v10_3_kfd2kgd,
798c2ecf20Sopenharmony_ci};
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci#ifdef KFD_SUPPORT_IOMMU_V2
828c2ecf20Sopenharmony_cistatic const struct kfd_device_info kaveri_device_info = {
838c2ecf20Sopenharmony_ci	.asic_family = CHIP_KAVERI,
848c2ecf20Sopenharmony_ci	.asic_name = "kaveri",
858c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
868c2ecf20Sopenharmony_ci	/* max num of queues for KV.TODO should be a dynamic value */
878c2ecf20Sopenharmony_ci	.max_no_of_hqd	= 24,
888c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
898c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
908c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
918c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
928c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
938c2ecf20Sopenharmony_ci	.supports_cwsr = false,
948c2ecf20Sopenharmony_ci	.needs_iommu_device = true,
958c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
968c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
978c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
988c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
998c2ecf20Sopenharmony_ci};
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cistatic const struct kfd_device_info carrizo_device_info = {
1028c2ecf20Sopenharmony_ci	.asic_family = CHIP_CARRIZO,
1038c2ecf20Sopenharmony_ci	.asic_name = "carrizo",
1048c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
1058c2ecf20Sopenharmony_ci	/* max num of queues for CZ.TODO should be a dynamic value */
1068c2ecf20Sopenharmony_ci	.max_no_of_hqd	= 24,
1078c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
1088c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
1098c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
1108c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
1118c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
1128c2ecf20Sopenharmony_ci	.supports_cwsr = true,
1138c2ecf20Sopenharmony_ci	.needs_iommu_device = true,
1148c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
1158c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
1168c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
1178c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
1188c2ecf20Sopenharmony_ci};
1198c2ecf20Sopenharmony_ci#endif
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic const struct kfd_device_info raven_device_info = {
1228c2ecf20Sopenharmony_ci	.asic_family = CHIP_RAVEN,
1238c2ecf20Sopenharmony_ci	.asic_name = "raven",
1248c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
1258c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
1268c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
1278c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
1288c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
1298c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
1308c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
1318c2ecf20Sopenharmony_ci	.supports_cwsr = true,
1328c2ecf20Sopenharmony_ci	.needs_iommu_device = true,
1338c2ecf20Sopenharmony_ci	.needs_pci_atomics = true,
1348c2ecf20Sopenharmony_ci	.num_sdma_engines = 1,
1358c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
1368c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
1378c2ecf20Sopenharmony_ci};
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic const struct kfd_device_info hawaii_device_info = {
1408c2ecf20Sopenharmony_ci	.asic_family = CHIP_HAWAII,
1418c2ecf20Sopenharmony_ci	.asic_name = "hawaii",
1428c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
1438c2ecf20Sopenharmony_ci	/* max num of queues for KV.TODO should be a dynamic value */
1448c2ecf20Sopenharmony_ci	.max_no_of_hqd	= 24,
1458c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
1468c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
1478c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
1488c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
1498c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
1508c2ecf20Sopenharmony_ci	.supports_cwsr = false,
1518c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
1528c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
1538c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
1548c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
1558c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
1568c2ecf20Sopenharmony_ci};
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic const struct kfd_device_info tonga_device_info = {
1598c2ecf20Sopenharmony_ci	.asic_family = CHIP_TONGA,
1608c2ecf20Sopenharmony_ci	.asic_name = "tonga",
1618c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
1628c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
1638c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
1648c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
1658c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
1668c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
1678c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
1688c2ecf20Sopenharmony_ci	.supports_cwsr = false,
1698c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
1708c2ecf20Sopenharmony_ci	.needs_pci_atomics = true,
1718c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
1728c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
1738c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
1748c2ecf20Sopenharmony_ci};
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_cistatic const struct kfd_device_info fiji_device_info = {
1778c2ecf20Sopenharmony_ci	.asic_family = CHIP_FIJI,
1788c2ecf20Sopenharmony_ci	.asic_name = "fiji",
1798c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
1808c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
1818c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
1828c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
1838c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
1848c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
1858c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
1868c2ecf20Sopenharmony_ci	.supports_cwsr = true,
1878c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
1888c2ecf20Sopenharmony_ci	.needs_pci_atomics = true,
1898c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
1908c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
1918c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
1928c2ecf20Sopenharmony_ci};
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic const struct kfd_device_info fiji_vf_device_info = {
1958c2ecf20Sopenharmony_ci	.asic_family = CHIP_FIJI,
1968c2ecf20Sopenharmony_ci	.asic_name = "fiji",
1978c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
1988c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
1998c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
2008c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
2018c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
2028c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
2038c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
2048c2ecf20Sopenharmony_ci	.supports_cwsr = true,
2058c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
2068c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
2078c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
2088c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
2098c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
2108c2ecf20Sopenharmony_ci};
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic const struct kfd_device_info polaris10_device_info = {
2148c2ecf20Sopenharmony_ci	.asic_family = CHIP_POLARIS10,
2158c2ecf20Sopenharmony_ci	.asic_name = "polaris10",
2168c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
2178c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
2188c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
2198c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
2208c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
2218c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
2228c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
2238c2ecf20Sopenharmony_ci	.supports_cwsr = true,
2248c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
2258c2ecf20Sopenharmony_ci	.needs_pci_atomics = true,
2268c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
2278c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
2288c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
2298c2ecf20Sopenharmony_ci};
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic const struct kfd_device_info polaris10_vf_device_info = {
2328c2ecf20Sopenharmony_ci	.asic_family = CHIP_POLARIS10,
2338c2ecf20Sopenharmony_ci	.asic_name = "polaris10",
2348c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
2358c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
2368c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
2378c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
2388c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
2398c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
2408c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
2418c2ecf20Sopenharmony_ci	.supports_cwsr = true,
2428c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
2438c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
2448c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
2458c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
2468c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
2478c2ecf20Sopenharmony_ci};
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic const struct kfd_device_info polaris11_device_info = {
2508c2ecf20Sopenharmony_ci	.asic_family = CHIP_POLARIS11,
2518c2ecf20Sopenharmony_ci	.asic_name = "polaris11",
2528c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
2538c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
2548c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
2558c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
2568c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
2578c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
2588c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
2598c2ecf20Sopenharmony_ci	.supports_cwsr = true,
2608c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
2618c2ecf20Sopenharmony_ci	.needs_pci_atomics = true,
2628c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
2638c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
2648c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
2658c2ecf20Sopenharmony_ci};
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_cistatic const struct kfd_device_info polaris12_device_info = {
2688c2ecf20Sopenharmony_ci	.asic_family = CHIP_POLARIS12,
2698c2ecf20Sopenharmony_ci	.asic_name = "polaris12",
2708c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
2718c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
2728c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
2738c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
2748c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
2758c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
2768c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
2778c2ecf20Sopenharmony_ci	.supports_cwsr = true,
2788c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
2798c2ecf20Sopenharmony_ci	.needs_pci_atomics = true,
2808c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
2818c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
2828c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
2838c2ecf20Sopenharmony_ci};
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistatic const struct kfd_device_info vegam_device_info = {
2868c2ecf20Sopenharmony_ci	.asic_family = CHIP_VEGAM,
2878c2ecf20Sopenharmony_ci	.asic_name = "vegam",
2888c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
2898c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
2908c2ecf20Sopenharmony_ci	.doorbell_size  = 4,
2918c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 4 * sizeof(uint32_t),
2928c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_cik,
2938c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
2948c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
2958c2ecf20Sopenharmony_ci	.supports_cwsr = true,
2968c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
2978c2ecf20Sopenharmony_ci	.needs_pci_atomics = true,
2988c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
2998c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
3008c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
3018c2ecf20Sopenharmony_ci};
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_cistatic const struct kfd_device_info vega10_device_info = {
3048c2ecf20Sopenharmony_ci	.asic_family = CHIP_VEGA10,
3058c2ecf20Sopenharmony_ci	.asic_name = "vega10",
3068c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
3078c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
3088c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
3098c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
3108c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
3118c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
3128c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
3138c2ecf20Sopenharmony_ci	.supports_cwsr = true,
3148c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
3158c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
3168c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
3178c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
3188c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
3198c2ecf20Sopenharmony_ci};
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic const struct kfd_device_info vega10_vf_device_info = {
3228c2ecf20Sopenharmony_ci	.asic_family = CHIP_VEGA10,
3238c2ecf20Sopenharmony_ci	.asic_name = "vega10",
3248c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
3258c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
3268c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
3278c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
3288c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
3298c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
3308c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
3318c2ecf20Sopenharmony_ci	.supports_cwsr = true,
3328c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
3338c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
3348c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
3358c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
3368c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
3378c2ecf20Sopenharmony_ci};
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic const struct kfd_device_info vega12_device_info = {
3408c2ecf20Sopenharmony_ci	.asic_family = CHIP_VEGA12,
3418c2ecf20Sopenharmony_ci	.asic_name = "vega12",
3428c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
3438c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
3448c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
3458c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
3468c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
3478c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
3488c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
3498c2ecf20Sopenharmony_ci	.supports_cwsr = true,
3508c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
3518c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
3528c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
3538c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
3548c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
3558c2ecf20Sopenharmony_ci};
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_cistatic const struct kfd_device_info vega20_device_info = {
3588c2ecf20Sopenharmony_ci	.asic_family = CHIP_VEGA20,
3598c2ecf20Sopenharmony_ci	.asic_name = "vega20",
3608c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
3618c2ecf20Sopenharmony_ci	.max_no_of_hqd	= 24,
3628c2ecf20Sopenharmony_ci	.doorbell_size	= 8,
3638c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
3648c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
3658c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
3668c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
3678c2ecf20Sopenharmony_ci	.supports_cwsr = true,
3688c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
3698c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
3708c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
3718c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
3728c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 8,
3738c2ecf20Sopenharmony_ci};
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_cistatic const struct kfd_device_info arcturus_device_info = {
3768c2ecf20Sopenharmony_ci	.asic_family = CHIP_ARCTURUS,
3778c2ecf20Sopenharmony_ci	.asic_name = "arcturus",
3788c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
3798c2ecf20Sopenharmony_ci	.max_no_of_hqd	= 24,
3808c2ecf20Sopenharmony_ci	.doorbell_size	= 8,
3818c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
3828c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
3838c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
3848c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
3858c2ecf20Sopenharmony_ci	.supports_cwsr = true,
3868c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
3878c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
3888c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
3898c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 6,
3908c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 8,
3918c2ecf20Sopenharmony_ci};
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cistatic const struct kfd_device_info renoir_device_info = {
3948c2ecf20Sopenharmony_ci	.asic_family = CHIP_RENOIR,
3958c2ecf20Sopenharmony_ci	.asic_name = "renoir",
3968c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
3978c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
3988c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
3998c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
4008c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
4018c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
4028c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
4038c2ecf20Sopenharmony_ci	.supports_cwsr = true,
4048c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
4058c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
4068c2ecf20Sopenharmony_ci	.num_sdma_engines = 1,
4078c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
4088c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 2,
4098c2ecf20Sopenharmony_ci};
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_cistatic const struct kfd_device_info navi10_device_info = {
4128c2ecf20Sopenharmony_ci	.asic_family = CHIP_NAVI10,
4138c2ecf20Sopenharmony_ci	.asic_name = "navi10",
4148c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
4158c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
4168c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
4178c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
4188c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
4198c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
4208c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
4218c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
4228c2ecf20Sopenharmony_ci	.supports_cwsr = true,
4238c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
4248c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
4258c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
4268c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 8,
4278c2ecf20Sopenharmony_ci};
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic const struct kfd_device_info navi12_device_info = {
4308c2ecf20Sopenharmony_ci	.asic_family = CHIP_NAVI12,
4318c2ecf20Sopenharmony_ci	.asic_name = "navi12",
4328c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
4338c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
4348c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
4358c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
4368c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
4378c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
4388c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
4398c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
4408c2ecf20Sopenharmony_ci	.supports_cwsr = true,
4418c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
4428c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
4438c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
4448c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 8,
4458c2ecf20Sopenharmony_ci};
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic const struct kfd_device_info navi14_device_info = {
4488c2ecf20Sopenharmony_ci	.asic_family = CHIP_NAVI14,
4498c2ecf20Sopenharmony_ci	.asic_name = "navi14",
4508c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
4518c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
4528c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
4538c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
4548c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
4558c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
4568c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
4578c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
4588c2ecf20Sopenharmony_ci	.supports_cwsr = true,
4598c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
4608c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
4618c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
4628c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 8,
4638c2ecf20Sopenharmony_ci};
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_cistatic const struct kfd_device_info sienna_cichlid_device_info = {
4668c2ecf20Sopenharmony_ci	.asic_family = CHIP_SIENNA_CICHLID,
4678c2ecf20Sopenharmony_ci	.asic_name = "sienna_cichlid",
4688c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
4698c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
4708c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
4718c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
4728c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
4738c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
4748c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
4758c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
4768c2ecf20Sopenharmony_ci	.supports_cwsr = true,
4778c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
4788c2ecf20Sopenharmony_ci	.num_sdma_engines = 4,
4798c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
4808c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 8,
4818c2ecf20Sopenharmony_ci};
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_cistatic const struct kfd_device_info navy_flounder_device_info = {
4848c2ecf20Sopenharmony_ci	.asic_family = CHIP_NAVY_FLOUNDER,
4858c2ecf20Sopenharmony_ci	.asic_name = "navy_flounder",
4868c2ecf20Sopenharmony_ci	.max_pasid_bits = 16,
4878c2ecf20Sopenharmony_ci	.max_no_of_hqd  = 24,
4888c2ecf20Sopenharmony_ci	.doorbell_size  = 8,
4898c2ecf20Sopenharmony_ci	.ih_ring_entry_size = 8 * sizeof(uint32_t),
4908c2ecf20Sopenharmony_ci	.event_interrupt_class = &event_interrupt_class_v9,
4918c2ecf20Sopenharmony_ci	.num_of_watch_points = 4,
4928c2ecf20Sopenharmony_ci	.mqd_size_aligned = MQD_SIZE_ALIGNED,
4938c2ecf20Sopenharmony_ci	.needs_iommu_device = false,
4948c2ecf20Sopenharmony_ci	.supports_cwsr = true,
4958c2ecf20Sopenharmony_ci	.needs_pci_atomics = false,
4968c2ecf20Sopenharmony_ci	.num_sdma_engines = 2,
4978c2ecf20Sopenharmony_ci	.num_xgmi_sdma_engines = 0,
4988c2ecf20Sopenharmony_ci	.num_sdma_queues_per_engine = 8,
4998c2ecf20Sopenharmony_ci};
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci/* For each entry, [0] is regular and [1] is virtualisation device. */
5028c2ecf20Sopenharmony_cistatic const struct kfd_device_info *kfd_supported_devices[][2] = {
5038c2ecf20Sopenharmony_ci#ifdef KFD_SUPPORT_IOMMU_V2
5048c2ecf20Sopenharmony_ci	[CHIP_KAVERI] = {&kaveri_device_info, NULL},
5058c2ecf20Sopenharmony_ci	[CHIP_CARRIZO] = {&carrizo_device_info, NULL},
5068c2ecf20Sopenharmony_ci#endif
5078c2ecf20Sopenharmony_ci	[CHIP_RAVEN] = {&raven_device_info, NULL},
5088c2ecf20Sopenharmony_ci	[CHIP_HAWAII] = {&hawaii_device_info, NULL},
5098c2ecf20Sopenharmony_ci	[CHIP_TONGA] = {&tonga_device_info, NULL},
5108c2ecf20Sopenharmony_ci	[CHIP_FIJI] = {&fiji_device_info, &fiji_vf_device_info},
5118c2ecf20Sopenharmony_ci	[CHIP_POLARIS10] = {&polaris10_device_info, &polaris10_vf_device_info},
5128c2ecf20Sopenharmony_ci	[CHIP_POLARIS11] = {&polaris11_device_info, NULL},
5138c2ecf20Sopenharmony_ci	[CHIP_POLARIS12] = {&polaris12_device_info, NULL},
5148c2ecf20Sopenharmony_ci	[CHIP_VEGAM] = {&vegam_device_info, NULL},
5158c2ecf20Sopenharmony_ci	[CHIP_VEGA10] = {&vega10_device_info, &vega10_vf_device_info},
5168c2ecf20Sopenharmony_ci	[CHIP_VEGA12] = {&vega12_device_info, NULL},
5178c2ecf20Sopenharmony_ci	[CHIP_VEGA20] = {&vega20_device_info, NULL},
5188c2ecf20Sopenharmony_ci	[CHIP_RENOIR] = {&renoir_device_info, NULL},
5198c2ecf20Sopenharmony_ci	[CHIP_ARCTURUS] = {&arcturus_device_info, &arcturus_device_info},
5208c2ecf20Sopenharmony_ci	[CHIP_NAVI10] = {&navi10_device_info, NULL},
5218c2ecf20Sopenharmony_ci	[CHIP_NAVI12] = {&navi12_device_info, &navi12_device_info},
5228c2ecf20Sopenharmony_ci	[CHIP_NAVI14] = {&navi14_device_info, NULL},
5238c2ecf20Sopenharmony_ci	[CHIP_SIENNA_CICHLID] = {&sienna_cichlid_device_info, &sienna_cichlid_device_info},
5248c2ecf20Sopenharmony_ci	[CHIP_NAVY_FLOUNDER] = {&navy_flounder_device_info, &navy_flounder_device_info},
5258c2ecf20Sopenharmony_ci};
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_cistatic int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
5288c2ecf20Sopenharmony_ci				unsigned int chunk_size);
5298c2ecf20Sopenharmony_cistatic void kfd_gtt_sa_fini(struct kfd_dev *kfd);
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_cistatic int kfd_resume(struct kfd_dev *kfd);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_cistruct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd,
5348c2ecf20Sopenharmony_ci	struct pci_dev *pdev, unsigned int asic_type, bool vf)
5358c2ecf20Sopenharmony_ci{
5368c2ecf20Sopenharmony_ci	struct kfd_dev *kfd;
5378c2ecf20Sopenharmony_ci	const struct kfd_device_info *device_info;
5388c2ecf20Sopenharmony_ci	const struct kfd2kgd_calls *f2g;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	if (asic_type >= sizeof(kfd_supported_devices) / (sizeof(void *) * 2)
5418c2ecf20Sopenharmony_ci		|| asic_type >= sizeof(kfd2kgd_funcs) / sizeof(void *)) {
5428c2ecf20Sopenharmony_ci		dev_err(kfd_device, "asic_type %d out of range\n", asic_type);
5438c2ecf20Sopenharmony_ci		return NULL; /* asic_type out of range */
5448c2ecf20Sopenharmony_ci	}
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	device_info = kfd_supported_devices[asic_type][vf];
5478c2ecf20Sopenharmony_ci	f2g = kfd2kgd_funcs[asic_type];
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	if (!device_info || !f2g) {
5508c2ecf20Sopenharmony_ci		dev_err(kfd_device, "%s %s not supported in kfd\n",
5518c2ecf20Sopenharmony_ci			amdgpu_asic_name[asic_type], vf ? "VF" : "");
5528c2ecf20Sopenharmony_ci		return NULL;
5538c2ecf20Sopenharmony_ci	}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	kfd = kzalloc(sizeof(*kfd), GFP_KERNEL);
5568c2ecf20Sopenharmony_ci	if (!kfd)
5578c2ecf20Sopenharmony_ci		return NULL;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	/* Allow BIF to recode atomics to PCIe 3.0 AtomicOps.
5608c2ecf20Sopenharmony_ci	 * 32 and 64-bit requests are possible and must be
5618c2ecf20Sopenharmony_ci	 * supported.
5628c2ecf20Sopenharmony_ci	 */
5638c2ecf20Sopenharmony_ci	kfd->pci_atomic_requested = amdgpu_amdkfd_have_atomics_support(kgd);
5648c2ecf20Sopenharmony_ci	if (device_info->needs_pci_atomics &&
5658c2ecf20Sopenharmony_ci	    !kfd->pci_atomic_requested) {
5668c2ecf20Sopenharmony_ci		dev_info(kfd_device,
5678c2ecf20Sopenharmony_ci			 "skipped device %x:%x, PCI rejects atomics\n",
5688c2ecf20Sopenharmony_ci			 pdev->vendor, pdev->device);
5698c2ecf20Sopenharmony_ci		kfree(kfd);
5708c2ecf20Sopenharmony_ci		return NULL;
5718c2ecf20Sopenharmony_ci	}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	kfd->kgd = kgd;
5748c2ecf20Sopenharmony_ci	kfd->device_info = device_info;
5758c2ecf20Sopenharmony_ci	kfd->pdev = pdev;
5768c2ecf20Sopenharmony_ci	kfd->init_complete = false;
5778c2ecf20Sopenharmony_ci	kfd->kfd2kgd = f2g;
5788c2ecf20Sopenharmony_ci	atomic_set(&kfd->compute_profile, 0);
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	mutex_init(&kfd->doorbell_mutex);
5818c2ecf20Sopenharmony_ci	memset(&kfd->doorbell_available_index, 0,
5828c2ecf20Sopenharmony_ci		sizeof(kfd->doorbell_available_index));
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	atomic_set(&kfd->sram_ecc_flag, 0);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	ida_init(&kfd->doorbell_ida);
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	return kfd;
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_cistatic void kfd_cwsr_init(struct kfd_dev *kfd)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	if (cwsr_enable && kfd->device_info->supports_cwsr) {
5948c2ecf20Sopenharmony_ci		if (kfd->device_info->asic_family < CHIP_VEGA10) {
5958c2ecf20Sopenharmony_ci			BUILD_BUG_ON(sizeof(cwsr_trap_gfx8_hex) > PAGE_SIZE);
5968c2ecf20Sopenharmony_ci			kfd->cwsr_isa = cwsr_trap_gfx8_hex;
5978c2ecf20Sopenharmony_ci			kfd->cwsr_isa_size = sizeof(cwsr_trap_gfx8_hex);
5988c2ecf20Sopenharmony_ci		} else if (kfd->device_info->asic_family == CHIP_ARCTURUS) {
5998c2ecf20Sopenharmony_ci			BUILD_BUG_ON(sizeof(cwsr_trap_arcturus_hex) > PAGE_SIZE);
6008c2ecf20Sopenharmony_ci			kfd->cwsr_isa = cwsr_trap_arcturus_hex;
6018c2ecf20Sopenharmony_ci			kfd->cwsr_isa_size = sizeof(cwsr_trap_arcturus_hex);
6028c2ecf20Sopenharmony_ci		} else if (kfd->device_info->asic_family < CHIP_NAVI10) {
6038c2ecf20Sopenharmony_ci			BUILD_BUG_ON(sizeof(cwsr_trap_gfx9_hex) > PAGE_SIZE);
6048c2ecf20Sopenharmony_ci			kfd->cwsr_isa = cwsr_trap_gfx9_hex;
6058c2ecf20Sopenharmony_ci			kfd->cwsr_isa_size = sizeof(cwsr_trap_gfx9_hex);
6068c2ecf20Sopenharmony_ci		} else if (kfd->device_info->asic_family < CHIP_SIENNA_CICHLID) {
6078c2ecf20Sopenharmony_ci			BUILD_BUG_ON(sizeof(cwsr_trap_nv1x_hex) > PAGE_SIZE);
6088c2ecf20Sopenharmony_ci			kfd->cwsr_isa = cwsr_trap_nv1x_hex;
6098c2ecf20Sopenharmony_ci			kfd->cwsr_isa_size = sizeof(cwsr_trap_nv1x_hex);
6108c2ecf20Sopenharmony_ci		} else {
6118c2ecf20Sopenharmony_ci			BUILD_BUG_ON(sizeof(cwsr_trap_gfx10_hex) > PAGE_SIZE);
6128c2ecf20Sopenharmony_ci			kfd->cwsr_isa = cwsr_trap_gfx10_hex;
6138c2ecf20Sopenharmony_ci			kfd->cwsr_isa_size = sizeof(cwsr_trap_gfx10_hex);
6148c2ecf20Sopenharmony_ci		}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci		kfd->cwsr_enabled = true;
6178c2ecf20Sopenharmony_ci	}
6188c2ecf20Sopenharmony_ci}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_cistatic int kfd_gws_init(struct kfd_dev *kfd)
6218c2ecf20Sopenharmony_ci{
6228c2ecf20Sopenharmony_ci	int ret = 0;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	if (kfd->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
6258c2ecf20Sopenharmony_ci		return 0;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	if (hws_gws_support
6288c2ecf20Sopenharmony_ci		|| (kfd->device_info->asic_family == CHIP_VEGA10
6298c2ecf20Sopenharmony_ci			&& kfd->mec2_fw_version >= 0x81b3)
6308c2ecf20Sopenharmony_ci		|| (kfd->device_info->asic_family >= CHIP_VEGA12
6318c2ecf20Sopenharmony_ci			&& kfd->device_info->asic_family <= CHIP_RAVEN
6328c2ecf20Sopenharmony_ci			&& kfd->mec2_fw_version >= 0x1b3)
6338c2ecf20Sopenharmony_ci		|| (kfd->device_info->asic_family == CHIP_ARCTURUS
6348c2ecf20Sopenharmony_ci			&& kfd->mec2_fw_version >= 0x30))
6358c2ecf20Sopenharmony_ci		ret = amdgpu_amdkfd_alloc_gws(kfd->kgd,
6368c2ecf20Sopenharmony_ci				amdgpu_amdkfd_get_num_gws(kfd->kgd), &kfd->gws);
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	return ret;
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cistatic void kfd_smi_init(struct kfd_dev *dev) {
6428c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dev->smi_clients);
6438c2ecf20Sopenharmony_ci	spin_lock_init(&dev->smi_lock);
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_cibool kgd2kfd_device_init(struct kfd_dev *kfd,
6478c2ecf20Sopenharmony_ci			 struct drm_device *ddev,
6488c2ecf20Sopenharmony_ci			 const struct kgd2kfd_shared_resources *gpu_resources)
6498c2ecf20Sopenharmony_ci{
6508c2ecf20Sopenharmony_ci	unsigned int size;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	kfd->ddev = ddev;
6538c2ecf20Sopenharmony_ci	kfd->mec_fw_version = amdgpu_amdkfd_get_fw_version(kfd->kgd,
6548c2ecf20Sopenharmony_ci			KGD_ENGINE_MEC1);
6558c2ecf20Sopenharmony_ci	kfd->mec2_fw_version = amdgpu_amdkfd_get_fw_version(kfd->kgd,
6568c2ecf20Sopenharmony_ci			KGD_ENGINE_MEC2);
6578c2ecf20Sopenharmony_ci	kfd->sdma_fw_version = amdgpu_amdkfd_get_fw_version(kfd->kgd,
6588c2ecf20Sopenharmony_ci			KGD_ENGINE_SDMA1);
6598c2ecf20Sopenharmony_ci	kfd->shared_resources = *gpu_resources;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	kfd->vm_info.first_vmid_kfd = ffs(gpu_resources->compute_vmid_bitmap)-1;
6628c2ecf20Sopenharmony_ci	kfd->vm_info.last_vmid_kfd = fls(gpu_resources->compute_vmid_bitmap)-1;
6638c2ecf20Sopenharmony_ci	kfd->vm_info.vmid_num_kfd = kfd->vm_info.last_vmid_kfd
6648c2ecf20Sopenharmony_ci			- kfd->vm_info.first_vmid_kfd + 1;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	/* Verify module parameters regarding mapped process number*/
6678c2ecf20Sopenharmony_ci	if (hws_max_conc_proc >= 0)
6688c2ecf20Sopenharmony_ci		kfd->max_proc_per_quantum = min((u32)hws_max_conc_proc, kfd->vm_info.vmid_num_kfd);
6698c2ecf20Sopenharmony_ci	else
6708c2ecf20Sopenharmony_ci		kfd->max_proc_per_quantum = kfd->vm_info.vmid_num_kfd;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	/* calculate max size of mqds needed for queues */
6738c2ecf20Sopenharmony_ci	size = max_num_of_queues_per_device *
6748c2ecf20Sopenharmony_ci			kfd->device_info->mqd_size_aligned;
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	/*
6778c2ecf20Sopenharmony_ci	 * calculate max size of runlist packet.
6788c2ecf20Sopenharmony_ci	 * There can be only 2 packets at once
6798c2ecf20Sopenharmony_ci	 */
6808c2ecf20Sopenharmony_ci	size += (KFD_MAX_NUM_OF_PROCESSES * sizeof(struct pm4_mes_map_process) +
6818c2ecf20Sopenharmony_ci		max_num_of_queues_per_device * sizeof(struct pm4_mes_map_queues)
6828c2ecf20Sopenharmony_ci		+ sizeof(struct pm4_mes_runlist)) * 2;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	/* Add size of HIQ & DIQ */
6858c2ecf20Sopenharmony_ci	size += KFD_KERNEL_QUEUE_SIZE * 2;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	/* add another 512KB for all other allocations on gart (HPD, fences) */
6888c2ecf20Sopenharmony_ci	size += 512 * 1024;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	if (amdgpu_amdkfd_alloc_gtt_mem(
6918c2ecf20Sopenharmony_ci			kfd->kgd, size, &kfd->gtt_mem,
6928c2ecf20Sopenharmony_ci			&kfd->gtt_start_gpu_addr, &kfd->gtt_start_cpu_ptr,
6938c2ecf20Sopenharmony_ci			false)) {
6948c2ecf20Sopenharmony_ci		dev_err(kfd_device, "Could not allocate %d bytes\n", size);
6958c2ecf20Sopenharmony_ci		goto alloc_gtt_mem_failure;
6968c2ecf20Sopenharmony_ci	}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	dev_info(kfd_device, "Allocated %d bytes on gart\n", size);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	/* Initialize GTT sa with 512 byte chunk size */
7018c2ecf20Sopenharmony_ci	if (kfd_gtt_sa_init(kfd, size, 512) != 0) {
7028c2ecf20Sopenharmony_ci		dev_err(kfd_device, "Error initializing gtt sub-allocator\n");
7038c2ecf20Sopenharmony_ci		goto kfd_gtt_sa_init_error;
7048c2ecf20Sopenharmony_ci	}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	if (kfd_doorbell_init(kfd)) {
7078c2ecf20Sopenharmony_ci		dev_err(kfd_device,
7088c2ecf20Sopenharmony_ci			"Error initializing doorbell aperture\n");
7098c2ecf20Sopenharmony_ci		goto kfd_doorbell_error;
7108c2ecf20Sopenharmony_ci	}
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	kfd->hive_id = amdgpu_amdkfd_get_hive_id(kfd->kgd);
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	kfd->unique_id = amdgpu_amdkfd_get_unique_id(kfd->kgd);
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	kfd->noretry = amdgpu_amdkfd_get_noretry(kfd->kgd);
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	if (kfd_interrupt_init(kfd)) {
7198c2ecf20Sopenharmony_ci		dev_err(kfd_device, "Error initializing interrupts\n");
7208c2ecf20Sopenharmony_ci		goto kfd_interrupt_error;
7218c2ecf20Sopenharmony_ci	}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	kfd->dqm = device_queue_manager_init(kfd);
7248c2ecf20Sopenharmony_ci	if (!kfd->dqm) {
7258c2ecf20Sopenharmony_ci		dev_err(kfd_device, "Error initializing queue manager\n");
7268c2ecf20Sopenharmony_ci		goto device_queue_manager_error;
7278c2ecf20Sopenharmony_ci	}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	/* If supported on this device, allocate global GWS that is shared
7308c2ecf20Sopenharmony_ci	 * by all KFD processes
7318c2ecf20Sopenharmony_ci	 */
7328c2ecf20Sopenharmony_ci	if (kfd_gws_init(kfd)) {
7338c2ecf20Sopenharmony_ci		dev_err(kfd_device, "Could not allocate %d gws\n",
7348c2ecf20Sopenharmony_ci			amdgpu_amdkfd_get_num_gws(kfd->kgd));
7358c2ecf20Sopenharmony_ci		goto gws_error;
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	/* If CRAT is broken, won't set iommu enabled */
7398c2ecf20Sopenharmony_ci	kfd_double_confirm_iommu_support(kfd);
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	if (kfd_iommu_device_init(kfd)) {
7428c2ecf20Sopenharmony_ci		kfd->use_iommu_v2 = false;
7438c2ecf20Sopenharmony_ci		dev_err(kfd_device, "Error initializing iommuv2\n");
7448c2ecf20Sopenharmony_ci		goto device_iommu_error;
7458c2ecf20Sopenharmony_ci	}
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	kfd_cwsr_init(kfd);
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	if(kgd2kfd_resume_iommu(kfd))
7508c2ecf20Sopenharmony_ci		goto device_iommu_error;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	if (kfd_resume(kfd))
7538c2ecf20Sopenharmony_ci		goto kfd_resume_error;
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	kfd->dbgmgr = NULL;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	if (kfd_topology_add_device(kfd)) {
7588c2ecf20Sopenharmony_ci		dev_err(kfd_device, "Error adding device to topology\n");
7598c2ecf20Sopenharmony_ci		goto kfd_topology_add_device_error;
7608c2ecf20Sopenharmony_ci	}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	kfd_smi_init(kfd);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	kfd->init_complete = true;
7658c2ecf20Sopenharmony_ci	dev_info(kfd_device, "added device %x:%x\n", kfd->pdev->vendor,
7668c2ecf20Sopenharmony_ci		 kfd->pdev->device);
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	pr_debug("Starting kfd with the following scheduling policy %d\n",
7698c2ecf20Sopenharmony_ci		kfd->dqm->sched_policy);
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	goto out;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_cikfd_topology_add_device_error:
7748c2ecf20Sopenharmony_cikfd_resume_error:
7758c2ecf20Sopenharmony_cidevice_iommu_error:
7768c2ecf20Sopenharmony_cigws_error:
7778c2ecf20Sopenharmony_ci	device_queue_manager_uninit(kfd->dqm);
7788c2ecf20Sopenharmony_cidevice_queue_manager_error:
7798c2ecf20Sopenharmony_ci	kfd_interrupt_exit(kfd);
7808c2ecf20Sopenharmony_cikfd_interrupt_error:
7818c2ecf20Sopenharmony_ci	kfd_doorbell_fini(kfd);
7828c2ecf20Sopenharmony_cikfd_doorbell_error:
7838c2ecf20Sopenharmony_ci	kfd_gtt_sa_fini(kfd);
7848c2ecf20Sopenharmony_cikfd_gtt_sa_init_error:
7858c2ecf20Sopenharmony_ci	amdgpu_amdkfd_free_gtt_mem(kfd->kgd, kfd->gtt_mem);
7868c2ecf20Sopenharmony_cialloc_gtt_mem_failure:
7878c2ecf20Sopenharmony_ci	if (kfd->gws)
7888c2ecf20Sopenharmony_ci		amdgpu_amdkfd_free_gws(kfd->kgd, kfd->gws);
7898c2ecf20Sopenharmony_ci	dev_err(kfd_device,
7908c2ecf20Sopenharmony_ci		"device %x:%x NOT added due to errors\n",
7918c2ecf20Sopenharmony_ci		kfd->pdev->vendor, kfd->pdev->device);
7928c2ecf20Sopenharmony_ciout:
7938c2ecf20Sopenharmony_ci	return kfd->init_complete;
7948c2ecf20Sopenharmony_ci}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_civoid kgd2kfd_device_exit(struct kfd_dev *kfd)
7978c2ecf20Sopenharmony_ci{
7988c2ecf20Sopenharmony_ci	if (kfd->init_complete) {
7998c2ecf20Sopenharmony_ci		kgd2kfd_suspend(kfd, false);
8008c2ecf20Sopenharmony_ci		device_queue_manager_uninit(kfd->dqm);
8018c2ecf20Sopenharmony_ci		kfd_interrupt_exit(kfd);
8028c2ecf20Sopenharmony_ci		kfd_topology_remove_device(kfd);
8038c2ecf20Sopenharmony_ci		kfd_doorbell_fini(kfd);
8048c2ecf20Sopenharmony_ci		ida_destroy(&kfd->doorbell_ida);
8058c2ecf20Sopenharmony_ci		kfd_gtt_sa_fini(kfd);
8068c2ecf20Sopenharmony_ci		amdgpu_amdkfd_free_gtt_mem(kfd->kgd, kfd->gtt_mem);
8078c2ecf20Sopenharmony_ci		if (kfd->gws)
8088c2ecf20Sopenharmony_ci			amdgpu_amdkfd_free_gws(kfd->kgd, kfd->gws);
8098c2ecf20Sopenharmony_ci	}
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	kfree(kfd);
8128c2ecf20Sopenharmony_ci}
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ciint kgd2kfd_pre_reset(struct kfd_dev *kfd)
8158c2ecf20Sopenharmony_ci{
8168c2ecf20Sopenharmony_ci	if (!kfd->init_complete)
8178c2ecf20Sopenharmony_ci		return 0;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	kfd_smi_event_update_gpu_reset(kfd, false);
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	kfd->dqm->ops.pre_reset(kfd->dqm);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	kgd2kfd_suspend(kfd, false);
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	kfd_signal_reset_event(kfd);
8268c2ecf20Sopenharmony_ci	return 0;
8278c2ecf20Sopenharmony_ci}
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci/*
8308c2ecf20Sopenharmony_ci * Fix me. KFD won't be able to resume existing process for now.
8318c2ecf20Sopenharmony_ci * We will keep all existing process in a evicted state and
8328c2ecf20Sopenharmony_ci * wait the process to be terminated.
8338c2ecf20Sopenharmony_ci */
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ciint kgd2kfd_post_reset(struct kfd_dev *kfd)
8368c2ecf20Sopenharmony_ci{
8378c2ecf20Sopenharmony_ci	int ret;
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	if (!kfd->init_complete)
8408c2ecf20Sopenharmony_ci		return 0;
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	ret = kfd_resume(kfd);
8438c2ecf20Sopenharmony_ci	if (ret)
8448c2ecf20Sopenharmony_ci		return ret;
8458c2ecf20Sopenharmony_ci	atomic_dec(&kfd_locked);
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	atomic_set(&kfd->sram_ecc_flag, 0);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	kfd_smi_event_update_gpu_reset(kfd, true);
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	return 0;
8528c2ecf20Sopenharmony_ci}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_cibool kfd_is_locked(void)
8558c2ecf20Sopenharmony_ci{
8568c2ecf20Sopenharmony_ci	return  (atomic_read(&kfd_locked) > 0);
8578c2ecf20Sopenharmony_ci}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_civoid kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm)
8608c2ecf20Sopenharmony_ci{
8618c2ecf20Sopenharmony_ci	if (!kfd->init_complete)
8628c2ecf20Sopenharmony_ci		return;
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	/* for runtime suspend, skip locking kfd */
8658c2ecf20Sopenharmony_ci	if (!run_pm) {
8668c2ecf20Sopenharmony_ci		/* For first KFD device suspend all the KFD processes */
8678c2ecf20Sopenharmony_ci		if (atomic_inc_return(&kfd_locked) == 1)
8688c2ecf20Sopenharmony_ci			kfd_suspend_all_processes();
8698c2ecf20Sopenharmony_ci	}
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	kfd->dqm->ops.stop(kfd->dqm);
8728c2ecf20Sopenharmony_ci	kfd_iommu_suspend(kfd);
8738c2ecf20Sopenharmony_ci}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ciint kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)
8768c2ecf20Sopenharmony_ci{
8778c2ecf20Sopenharmony_ci	int ret, count;
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	if (!kfd->init_complete)
8808c2ecf20Sopenharmony_ci		return 0;
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	ret = kfd_resume(kfd);
8838c2ecf20Sopenharmony_ci	if (ret)
8848c2ecf20Sopenharmony_ci		return ret;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	/* for runtime resume, skip unlocking kfd */
8878c2ecf20Sopenharmony_ci	if (!run_pm) {
8888c2ecf20Sopenharmony_ci		count = atomic_dec_return(&kfd_locked);
8898c2ecf20Sopenharmony_ci		WARN_ONCE(count < 0, "KFD suspend / resume ref. error");
8908c2ecf20Sopenharmony_ci		if (count == 0)
8918c2ecf20Sopenharmony_ci			ret = kfd_resume_all_processes();
8928c2ecf20Sopenharmony_ci	}
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci	return ret;
8958c2ecf20Sopenharmony_ci}
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ciint kgd2kfd_resume_iommu(struct kfd_dev *kfd)
8988c2ecf20Sopenharmony_ci{
8998c2ecf20Sopenharmony_ci	int err = 0;
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	err = kfd_iommu_resume(kfd);
9028c2ecf20Sopenharmony_ci	if (err)
9038c2ecf20Sopenharmony_ci		dev_err(kfd_device,
9048c2ecf20Sopenharmony_ci			"Failed to resume IOMMU for device %x:%x\n",
9058c2ecf20Sopenharmony_ci			kfd->pdev->vendor, kfd->pdev->device);
9068c2ecf20Sopenharmony_ci	return err;
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_cistatic int kfd_resume(struct kfd_dev *kfd)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	int err = 0;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	err = kfd->dqm->ops.start(kfd->dqm);
9148c2ecf20Sopenharmony_ci	if (err) {
9158c2ecf20Sopenharmony_ci		dev_err(kfd_device,
9168c2ecf20Sopenharmony_ci			"Error starting queue manager for device %x:%x\n",
9178c2ecf20Sopenharmony_ci			kfd->pdev->vendor, kfd->pdev->device);
9188c2ecf20Sopenharmony_ci		goto dqm_start_error;
9198c2ecf20Sopenharmony_ci	}
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	return err;
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_cidqm_start_error:
9248c2ecf20Sopenharmony_ci	kfd_iommu_suspend(kfd);
9258c2ecf20Sopenharmony_ci	return err;
9268c2ecf20Sopenharmony_ci}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_cistatic inline void kfd_queue_work(struct workqueue_struct *wq,
9298c2ecf20Sopenharmony_ci				  struct work_struct *work)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	int cpu, new_cpu;
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	cpu = new_cpu = smp_processor_id();
9348c2ecf20Sopenharmony_ci	do {
9358c2ecf20Sopenharmony_ci		new_cpu = cpumask_next(new_cpu, cpu_online_mask) % nr_cpu_ids;
9368c2ecf20Sopenharmony_ci		if (cpu_to_node(new_cpu) == numa_node_id())
9378c2ecf20Sopenharmony_ci			break;
9388c2ecf20Sopenharmony_ci	} while (cpu != new_cpu);
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	queue_work_on(new_cpu, wq, work);
9418c2ecf20Sopenharmony_ci}
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci/* This is called directly from KGD at ISR. */
9448c2ecf20Sopenharmony_civoid kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
9458c2ecf20Sopenharmony_ci{
9468c2ecf20Sopenharmony_ci	uint32_t patched_ihre[KFD_MAX_RING_ENTRY_SIZE];
9478c2ecf20Sopenharmony_ci	bool is_patched = false;
9488c2ecf20Sopenharmony_ci	unsigned long flags;
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	if (!kfd->init_complete)
9518c2ecf20Sopenharmony_ci		return;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	if (kfd->device_info->ih_ring_entry_size > sizeof(patched_ihre)) {
9548c2ecf20Sopenharmony_ci		dev_err_once(kfd_device, "Ring entry too small\n");
9558c2ecf20Sopenharmony_ci		return;
9568c2ecf20Sopenharmony_ci	}
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	spin_lock_irqsave(&kfd->interrupt_lock, flags);
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci	if (kfd->interrupts_active
9618c2ecf20Sopenharmony_ci	    && interrupt_is_wanted(kfd, ih_ring_entry,
9628c2ecf20Sopenharmony_ci				   patched_ihre, &is_patched)
9638c2ecf20Sopenharmony_ci	    && enqueue_ih_ring_entry(kfd,
9648c2ecf20Sopenharmony_ci				     is_patched ? patched_ihre : ih_ring_entry))
9658c2ecf20Sopenharmony_ci		kfd_queue_work(kfd->ih_wq, &kfd->interrupt_work);
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&kfd->interrupt_lock, flags);
9688c2ecf20Sopenharmony_ci}
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ciint kgd2kfd_quiesce_mm(struct mm_struct *mm)
9718c2ecf20Sopenharmony_ci{
9728c2ecf20Sopenharmony_ci	struct kfd_process *p;
9738c2ecf20Sopenharmony_ci	int r;
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	/* Because we are called from arbitrary context (workqueue) as opposed
9768c2ecf20Sopenharmony_ci	 * to process context, kfd_process could attempt to exit while we are
9778c2ecf20Sopenharmony_ci	 * running so the lookup function increments the process ref count.
9788c2ecf20Sopenharmony_ci	 */
9798c2ecf20Sopenharmony_ci	p = kfd_lookup_process_by_mm(mm);
9808c2ecf20Sopenharmony_ci	if (!p)
9818c2ecf20Sopenharmony_ci		return -ESRCH;
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	WARN(debug_evictions, "Evicting pid %d", p->lead_thread->pid);
9848c2ecf20Sopenharmony_ci	r = kfd_process_evict_queues(p);
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	kfd_unref_process(p);
9878c2ecf20Sopenharmony_ci	return r;
9888c2ecf20Sopenharmony_ci}
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ciint kgd2kfd_resume_mm(struct mm_struct *mm)
9918c2ecf20Sopenharmony_ci{
9928c2ecf20Sopenharmony_ci	struct kfd_process *p;
9938c2ecf20Sopenharmony_ci	int r;
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	/* Because we are called from arbitrary context (workqueue) as opposed
9968c2ecf20Sopenharmony_ci	 * to process context, kfd_process could attempt to exit while we are
9978c2ecf20Sopenharmony_ci	 * running so the lookup function increments the process ref count.
9988c2ecf20Sopenharmony_ci	 */
9998c2ecf20Sopenharmony_ci	p = kfd_lookup_process_by_mm(mm);
10008c2ecf20Sopenharmony_ci	if (!p)
10018c2ecf20Sopenharmony_ci		return -ESRCH;
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	r = kfd_process_restore_queues(p);
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	kfd_unref_process(p);
10068c2ecf20Sopenharmony_ci	return r;
10078c2ecf20Sopenharmony_ci}
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci/** kgd2kfd_schedule_evict_and_restore_process - Schedules work queue that will
10108c2ecf20Sopenharmony_ci *   prepare for safe eviction of KFD BOs that belong to the specified
10118c2ecf20Sopenharmony_ci *   process.
10128c2ecf20Sopenharmony_ci *
10138c2ecf20Sopenharmony_ci * @mm: mm_struct that identifies the specified KFD process
10148c2ecf20Sopenharmony_ci * @fence: eviction fence attached to KFD process BOs
10158c2ecf20Sopenharmony_ci *
10168c2ecf20Sopenharmony_ci */
10178c2ecf20Sopenharmony_ciint kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
10188c2ecf20Sopenharmony_ci					       struct dma_fence *fence)
10198c2ecf20Sopenharmony_ci{
10208c2ecf20Sopenharmony_ci	struct kfd_process *p;
10218c2ecf20Sopenharmony_ci	unsigned long active_time;
10228c2ecf20Sopenharmony_ci	unsigned long delay_jiffies = msecs_to_jiffies(PROCESS_ACTIVE_TIME_MS);
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	if (!fence)
10258c2ecf20Sopenharmony_ci		return -EINVAL;
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	if (dma_fence_is_signaled(fence))
10288c2ecf20Sopenharmony_ci		return 0;
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci	p = kfd_lookup_process_by_mm(mm);
10318c2ecf20Sopenharmony_ci	if (!p)
10328c2ecf20Sopenharmony_ci		return -ENODEV;
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	if (fence->seqno == p->last_eviction_seqno)
10358c2ecf20Sopenharmony_ci		goto out;
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	p->last_eviction_seqno = fence->seqno;
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	/* Avoid KFD process starvation. Wait for at least
10408c2ecf20Sopenharmony_ci	 * PROCESS_ACTIVE_TIME_MS before evicting the process again
10418c2ecf20Sopenharmony_ci	 */
10428c2ecf20Sopenharmony_ci	active_time = get_jiffies_64() - p->last_restore_timestamp;
10438c2ecf20Sopenharmony_ci	if (delay_jiffies > active_time)
10448c2ecf20Sopenharmony_ci		delay_jiffies -= active_time;
10458c2ecf20Sopenharmony_ci	else
10468c2ecf20Sopenharmony_ci		delay_jiffies = 0;
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	/* During process initialization eviction_work.dwork is initialized
10498c2ecf20Sopenharmony_ci	 * to kfd_evict_bo_worker
10508c2ecf20Sopenharmony_ci	 */
10518c2ecf20Sopenharmony_ci	WARN(debug_evictions, "Scheduling eviction of pid %d in %ld jiffies",
10528c2ecf20Sopenharmony_ci	     p->lead_thread->pid, delay_jiffies);
10538c2ecf20Sopenharmony_ci	schedule_delayed_work(&p->eviction_work, delay_jiffies);
10548c2ecf20Sopenharmony_ciout:
10558c2ecf20Sopenharmony_ci	kfd_unref_process(p);
10568c2ecf20Sopenharmony_ci	return 0;
10578c2ecf20Sopenharmony_ci}
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_cistatic int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
10608c2ecf20Sopenharmony_ci				unsigned int chunk_size)
10618c2ecf20Sopenharmony_ci{
10628c2ecf20Sopenharmony_ci	unsigned int num_of_longs;
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	if (WARN_ON(buf_size < chunk_size))
10658c2ecf20Sopenharmony_ci		return -EINVAL;
10668c2ecf20Sopenharmony_ci	if (WARN_ON(buf_size == 0))
10678c2ecf20Sopenharmony_ci		return -EINVAL;
10688c2ecf20Sopenharmony_ci	if (WARN_ON(chunk_size == 0))
10698c2ecf20Sopenharmony_ci		return -EINVAL;
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	kfd->gtt_sa_chunk_size = chunk_size;
10728c2ecf20Sopenharmony_ci	kfd->gtt_sa_num_of_chunks = buf_size / chunk_size;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	num_of_longs = (kfd->gtt_sa_num_of_chunks + BITS_PER_LONG - 1) /
10758c2ecf20Sopenharmony_ci		BITS_PER_LONG;
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	kfd->gtt_sa_bitmap = kcalloc(num_of_longs, sizeof(long), GFP_KERNEL);
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	if (!kfd->gtt_sa_bitmap)
10808c2ecf20Sopenharmony_ci		return -ENOMEM;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	pr_debug("gtt_sa_num_of_chunks = %d, gtt_sa_bitmap = %p\n",
10838c2ecf20Sopenharmony_ci			kfd->gtt_sa_num_of_chunks, kfd->gtt_sa_bitmap);
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	mutex_init(&kfd->gtt_sa_lock);
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	return 0;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci}
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_cistatic void kfd_gtt_sa_fini(struct kfd_dev *kfd)
10928c2ecf20Sopenharmony_ci{
10938c2ecf20Sopenharmony_ci	mutex_destroy(&kfd->gtt_sa_lock);
10948c2ecf20Sopenharmony_ci	kfree(kfd->gtt_sa_bitmap);
10958c2ecf20Sopenharmony_ci}
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_cistatic inline uint64_t kfd_gtt_sa_calc_gpu_addr(uint64_t start_addr,
10988c2ecf20Sopenharmony_ci						unsigned int bit_num,
10998c2ecf20Sopenharmony_ci						unsigned int chunk_size)
11008c2ecf20Sopenharmony_ci{
11018c2ecf20Sopenharmony_ci	return start_addr + bit_num * chunk_size;
11028c2ecf20Sopenharmony_ci}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_cistatic inline uint32_t *kfd_gtt_sa_calc_cpu_addr(void *start_addr,
11058c2ecf20Sopenharmony_ci						unsigned int bit_num,
11068c2ecf20Sopenharmony_ci						unsigned int chunk_size)
11078c2ecf20Sopenharmony_ci{
11088c2ecf20Sopenharmony_ci	return (uint32_t *) ((uint64_t) start_addr + bit_num * chunk_size);
11098c2ecf20Sopenharmony_ci}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ciint kfd_gtt_sa_allocate(struct kfd_dev *kfd, unsigned int size,
11128c2ecf20Sopenharmony_ci			struct kfd_mem_obj **mem_obj)
11138c2ecf20Sopenharmony_ci{
11148c2ecf20Sopenharmony_ci	unsigned int found, start_search, cur_size;
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	if (size == 0)
11178c2ecf20Sopenharmony_ci		return -EINVAL;
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	if (size > kfd->gtt_sa_num_of_chunks * kfd->gtt_sa_chunk_size)
11208c2ecf20Sopenharmony_ci		return -ENOMEM;
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	*mem_obj = kzalloc(sizeof(struct kfd_mem_obj), GFP_KERNEL);
11238c2ecf20Sopenharmony_ci	if (!(*mem_obj))
11248c2ecf20Sopenharmony_ci		return -ENOMEM;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	pr_debug("Allocated mem_obj = %p for size = %d\n", *mem_obj, size);
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	start_search = 0;
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	mutex_lock(&kfd->gtt_sa_lock);
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_cikfd_gtt_restart_search:
11338c2ecf20Sopenharmony_ci	/* Find the first chunk that is free */
11348c2ecf20Sopenharmony_ci	found = find_next_zero_bit(kfd->gtt_sa_bitmap,
11358c2ecf20Sopenharmony_ci					kfd->gtt_sa_num_of_chunks,
11368c2ecf20Sopenharmony_ci					start_search);
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	pr_debug("Found = %d\n", found);
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci	/* If there wasn't any free chunk, bail out */
11418c2ecf20Sopenharmony_ci	if (found == kfd->gtt_sa_num_of_chunks)
11428c2ecf20Sopenharmony_ci		goto kfd_gtt_no_free_chunk;
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci	/* Update fields of mem_obj */
11458c2ecf20Sopenharmony_ci	(*mem_obj)->range_start = found;
11468c2ecf20Sopenharmony_ci	(*mem_obj)->range_end = found;
11478c2ecf20Sopenharmony_ci	(*mem_obj)->gpu_addr = kfd_gtt_sa_calc_gpu_addr(
11488c2ecf20Sopenharmony_ci					kfd->gtt_start_gpu_addr,
11498c2ecf20Sopenharmony_ci					found,
11508c2ecf20Sopenharmony_ci					kfd->gtt_sa_chunk_size);
11518c2ecf20Sopenharmony_ci	(*mem_obj)->cpu_ptr = kfd_gtt_sa_calc_cpu_addr(
11528c2ecf20Sopenharmony_ci					kfd->gtt_start_cpu_ptr,
11538c2ecf20Sopenharmony_ci					found,
11548c2ecf20Sopenharmony_ci					kfd->gtt_sa_chunk_size);
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	pr_debug("gpu_addr = %p, cpu_addr = %p\n",
11578c2ecf20Sopenharmony_ci			(uint64_t *) (*mem_obj)->gpu_addr, (*mem_obj)->cpu_ptr);
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	/* If we need only one chunk, mark it as allocated and get out */
11608c2ecf20Sopenharmony_ci	if (size <= kfd->gtt_sa_chunk_size) {
11618c2ecf20Sopenharmony_ci		pr_debug("Single bit\n");
11628c2ecf20Sopenharmony_ci		set_bit(found, kfd->gtt_sa_bitmap);
11638c2ecf20Sopenharmony_ci		goto kfd_gtt_out;
11648c2ecf20Sopenharmony_ci	}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	/* Otherwise, try to see if we have enough contiguous chunks */
11678c2ecf20Sopenharmony_ci	cur_size = size - kfd->gtt_sa_chunk_size;
11688c2ecf20Sopenharmony_ci	do {
11698c2ecf20Sopenharmony_ci		(*mem_obj)->range_end =
11708c2ecf20Sopenharmony_ci			find_next_zero_bit(kfd->gtt_sa_bitmap,
11718c2ecf20Sopenharmony_ci					kfd->gtt_sa_num_of_chunks, ++found);
11728c2ecf20Sopenharmony_ci		/*
11738c2ecf20Sopenharmony_ci		 * If next free chunk is not contiguous than we need to
11748c2ecf20Sopenharmony_ci		 * restart our search from the last free chunk we found (which
11758c2ecf20Sopenharmony_ci		 * wasn't contiguous to the previous ones
11768c2ecf20Sopenharmony_ci		 */
11778c2ecf20Sopenharmony_ci		if ((*mem_obj)->range_end != found) {
11788c2ecf20Sopenharmony_ci			start_search = found;
11798c2ecf20Sopenharmony_ci			goto kfd_gtt_restart_search;
11808c2ecf20Sopenharmony_ci		}
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci		/*
11838c2ecf20Sopenharmony_ci		 * If we reached end of buffer, bail out with error
11848c2ecf20Sopenharmony_ci		 */
11858c2ecf20Sopenharmony_ci		if (found == kfd->gtt_sa_num_of_chunks)
11868c2ecf20Sopenharmony_ci			goto kfd_gtt_no_free_chunk;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci		/* Check if we don't need another chunk */
11898c2ecf20Sopenharmony_ci		if (cur_size <= kfd->gtt_sa_chunk_size)
11908c2ecf20Sopenharmony_ci			cur_size = 0;
11918c2ecf20Sopenharmony_ci		else
11928c2ecf20Sopenharmony_ci			cur_size -= kfd->gtt_sa_chunk_size;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	} while (cur_size > 0);
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	pr_debug("range_start = %d, range_end = %d\n",
11978c2ecf20Sopenharmony_ci		(*mem_obj)->range_start, (*mem_obj)->range_end);
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	/* Mark the chunks as allocated */
12008c2ecf20Sopenharmony_ci	for (found = (*mem_obj)->range_start;
12018c2ecf20Sopenharmony_ci		found <= (*mem_obj)->range_end;
12028c2ecf20Sopenharmony_ci		found++)
12038c2ecf20Sopenharmony_ci		set_bit(found, kfd->gtt_sa_bitmap);
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_cikfd_gtt_out:
12068c2ecf20Sopenharmony_ci	mutex_unlock(&kfd->gtt_sa_lock);
12078c2ecf20Sopenharmony_ci	return 0;
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_cikfd_gtt_no_free_chunk:
12108c2ecf20Sopenharmony_ci	pr_debug("Allocation failed with mem_obj = %p\n", *mem_obj);
12118c2ecf20Sopenharmony_ci	mutex_unlock(&kfd->gtt_sa_lock);
12128c2ecf20Sopenharmony_ci	kfree(*mem_obj);
12138c2ecf20Sopenharmony_ci	return -ENOMEM;
12148c2ecf20Sopenharmony_ci}
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ciint kfd_gtt_sa_free(struct kfd_dev *kfd, struct kfd_mem_obj *mem_obj)
12178c2ecf20Sopenharmony_ci{
12188c2ecf20Sopenharmony_ci	unsigned int bit;
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	/* Act like kfree when trying to free a NULL object */
12218c2ecf20Sopenharmony_ci	if (!mem_obj)
12228c2ecf20Sopenharmony_ci		return 0;
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci	pr_debug("Free mem_obj = %p, range_start = %d, range_end = %d\n",
12258c2ecf20Sopenharmony_ci			mem_obj, mem_obj->range_start, mem_obj->range_end);
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	mutex_lock(&kfd->gtt_sa_lock);
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	/* Mark the chunks as free */
12308c2ecf20Sopenharmony_ci	for (bit = mem_obj->range_start;
12318c2ecf20Sopenharmony_ci		bit <= mem_obj->range_end;
12328c2ecf20Sopenharmony_ci		bit++)
12338c2ecf20Sopenharmony_ci		clear_bit(bit, kfd->gtt_sa_bitmap);
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_ci	mutex_unlock(&kfd->gtt_sa_lock);
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	kfree(mem_obj);
12388c2ecf20Sopenharmony_ci	return 0;
12398c2ecf20Sopenharmony_ci}
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_civoid kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd)
12428c2ecf20Sopenharmony_ci{
12438c2ecf20Sopenharmony_ci	if (kfd)
12448c2ecf20Sopenharmony_ci		atomic_inc(&kfd->sram_ecc_flag);
12458c2ecf20Sopenharmony_ci}
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_civoid kfd_inc_compute_active(struct kfd_dev *kfd)
12488c2ecf20Sopenharmony_ci{
12498c2ecf20Sopenharmony_ci	if (atomic_inc_return(&kfd->compute_profile) == 1)
12508c2ecf20Sopenharmony_ci		amdgpu_amdkfd_set_compute_idle(kfd->kgd, false);
12518c2ecf20Sopenharmony_ci}
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_civoid kfd_dec_compute_active(struct kfd_dev *kfd)
12548c2ecf20Sopenharmony_ci{
12558c2ecf20Sopenharmony_ci	int count = atomic_dec_return(&kfd->compute_profile);
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	if (count == 0)
12588c2ecf20Sopenharmony_ci		amdgpu_amdkfd_set_compute_idle(kfd->kgd, true);
12598c2ecf20Sopenharmony_ci	WARN_ONCE(count < 0, "Compute profile ref. count error");
12608c2ecf20Sopenharmony_ci}
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_civoid kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask)
12638c2ecf20Sopenharmony_ci{
12648c2ecf20Sopenharmony_ci	if (kfd)
12658c2ecf20Sopenharmony_ci		kfd_smi_event_update_thermal_throttling(kfd, throttle_bitmask);
12668c2ecf20Sopenharmony_ci}
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS)
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci/* This function will send a package to HIQ to hang the HWS
12718c2ecf20Sopenharmony_ci * which will trigger a GPU reset and bring the HWS back to normal state
12728c2ecf20Sopenharmony_ci */
12738c2ecf20Sopenharmony_ciint kfd_debugfs_hang_hws(struct kfd_dev *dev)
12748c2ecf20Sopenharmony_ci{
12758c2ecf20Sopenharmony_ci	int r = 0;
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	if (dev->dqm->sched_policy != KFD_SCHED_POLICY_HWS) {
12788c2ecf20Sopenharmony_ci		pr_err("HWS is not enabled");
12798c2ecf20Sopenharmony_ci		return -EINVAL;
12808c2ecf20Sopenharmony_ci	}
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	r = pm_debugfs_hang_hws(&dev->dqm->packets);
12838c2ecf20Sopenharmony_ci	if (!r)
12848c2ecf20Sopenharmony_ci		r = dqm_debugfs_execute_queues(dev->dqm);
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ci	return r;
12878c2ecf20Sopenharmony_ci}
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci#endif
1290