mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-6.5-2023-06-02: amdgpu: - SR-IOV fixes - Warning fixes - Misc code cleanups and spelling fixes - DCN 3.2 updates - Improved DC FAMS support for better power management - Improved DC SubVP support for better power management - DCN 3.1.x fixes - Max IB size query - DC GPU reset fixes - RAS updates - DCN 3.0.x fixes - S/G display fixes - CP shadow buffer support - Implement connector force callback - Z8 power improvements - PSP 13.0.10 vbflash support - Mode2 reset fixes - Store MQDs in VRAM to improve queue switch latency - VCN 3.x fixes - JPEG 3.x fixes - Enable DC_FP on LoongArch - GFXOFF fixes - GC 9.4.3 partition support - SDMA 4.4.2 partition support - VCN/JPEG 4.0.3 partition support - VCN 4.0.3 updates - NBIO 7.9 updates - GC 9.4.3 updates - Take NUMA into account when allocating memory - Handle NUMA for partitions - SMU 13.0.6 updates - GC 9.4.3 RAS updates - Stop including unused swiotlb.h - SMU 13.0.7 fixes - Fix clock output ordering on some APUs - Clean up DC FPGA code - GFX9 preemption fixes - Misc irq fixes - S0ix fixes - Add new DRM_AMDGPU_WERROR config parameter to help with CI - PCIe fix for RDNA2 - kdoc fixes - Documentation updates amdkfd: - Query TTM mem limit rather than hardcoding it - GC 9.4.3 partition support - Handle NUMA for partitions radeon: - Fix possible double free - Stop including unused swiotlb.h - Fix possible division by zero ttm: - Add query for TTM mem limit - Add NUMA awareness to pools - Export ttm_pool_fini() UAPI: - Add new ctx query flag to better handle GPU resets Mesa MR: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22290 - Add new interface to query and set shadow buffer for RDNA3 Mesa MR: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21986 - Add new INFO query for max IB size Proposed userspace: https://gitlab.freedesktop.org/bnieuwenhuizen/mesa/-/commits/ib-rejection-v3 amd-drm-next-6.5-2023-06-09: amdgpu: - S0ix fixes - Initial SMU13 Overdrive support - kdoc fixes - Misc clode cleanups - Flexible array fixes - Display OTG fixes - SMU 13.0.6 updates - Revert some broken clock counter updates - Misc display fixes - GFX9 preemption fixes - Add support for newer EEPROM bad page table format - Add missing radeon secondary id - Add support for new colorspace KMS API - CSA fix - Stable pstate fixes for APUs - make vbl interface admin only - Handle PCI accelerator class amdkfd: - Add debugger support for gdb radeon: - Fix possible UAF drm: - Add Colorspace functionality UAPI: - Add debugger interface for enabling gdb Proposed userspace: https://github.com/ROCm-Developer-Tools/ROCdbgapi/tree/wip-dbgapi - Add KMS colorspace API Discussion: https://lists.freedesktop.org/archives/dri-devel/2023-June/408128.html From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230609174817.7764-1-alexander.deucher@amd.com
This commit is contained in:
commit
901bdf5ea1
498 files changed
+45772
-8021
No files matched your search
@@ -5,6 +5,8 @@ Ryzen 4000 series, RENOIR, DCN 2.1, 9.3, VCN 2.2, 4.1.2, 11.0.3
|
||||
Ryzen 3000 series / AMD Ryzen Embedded V1*/R1* with Radeon Vega Gfx, RAVEN2, DCN 1.0, 9.2.2, VCN 1.0.1, 4.1.1, 10.0.1
|
||||
SteamDeck, VANGOGH, DCN 3.0.1, 10.3.1, VCN 3.1.0, 5.2.1, 11.5.0
|
||||
Ryzen 5000 series / Ryzen 7x30 series, GREEN SARDINE / Cezanne / Barcelo / Barcelo-R, DCN 2.1, 9.3, VCN 2.2, 4.1.1, 12.0.1
|
||||
Ryzen 6000 series / Ryzen 7x35 series, YELLOW CARP / Rembrandt / Rembrandt+, 3.1.2, 10.3.3, VCN 3.1.1, 5.2.3, 13.0.3
|
||||
Ryzen 6000 series / Ryzen 7x35 series / Ryzen 7x36 series, YELLOW CARP / Rembrandt / Rembrandt-R, 3.1.2, 10.3.3, VCN 3.1.1, 5.2.3, 13.0.3
|
||||
Ryzen 7000 series (AM5), Raphael, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
||||
Ryzen 7x45 series (FL1), / Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
||||
Ryzen 7x20 series, Mendocino, 3.1.6, 10.3.7, 3.1.1, 5.2.7, 13.0.8
|
||||
Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
|
||||
|
@@ -140,6 +140,7 @@ obj-$(CONFIG_DRM_TTM) += ttm/
|
||||
obj-$(CONFIG_DRM_SCHED) += scheduler/
|
||||
obj-$(CONFIG_DRM_RADEON)+= radeon/
|
||||
obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
|
||||
obj-$(CONFIG_DRM_AMDGPU)+= amd/amdxcp/
|
||||
obj-$(CONFIG_DRM_I915) += i915/
|
||||
obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/
|
||||
obj-$(CONFIG_DRM_MGAG200) += mgag200/
|
||||
|
||||
@@ -69,6 +69,16 @@ config DRM_AMDGPU_USERPTR
|
||||
This option selects CONFIG_HMM and CONFIG_HMM_MIRROR if it
|
||||
isn't already selected to enabled full userptr support.
|
||||
|
||||
config DRM_AMDGPU_WERROR
|
||||
bool "Force the compiler to throw an error instead of a warning when compiling"
|
||||
depends on DRM_AMDGPU
|
||||
depends on EXPERT
|
||||
depends on !COMPILE_TEST
|
||||
default n
|
||||
help
|
||||
Add -Werror to the build flags for amdgpu.ko.
|
||||
Only enable this if you are warning code for amdgpu.ko.
|
||||
|
||||
source "drivers/gpu/drm/amd/acp/Kconfig"
|
||||
source "drivers/gpu/drm/amd/display/Kconfig"
|
||||
source "drivers/gpu/drm/amd/amdkfd/Kconfig"
|
||||
@@ -39,6 +39,15 @@ ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \
|
||||
-I$(FULL_AMD_DISPLAY_PATH)/amdgpu_dm \
|
||||
-I$(FULL_AMD_PATH)/amdkfd
|
||||
|
||||
subdir-ccflags-y := -Wextra
|
||||
subdir-ccflags-y += $(call cc-option, -Wunused-but-set-variable)
|
||||
subdir-ccflags-y += -Wno-unused-parameter
|
||||
subdir-ccflags-y += -Wno-type-limits
|
||||
subdir-ccflags-y += -Wno-sign-compare
|
||||
subdir-ccflags-y += -Wno-missing-field-initializers
|
||||
subdir-ccflags-y += -Wno-override-init
|
||||
subdir-ccflags-$(CONFIG_DRM_AMDGPU_WERROR) += -Werror
|
||||
|
||||
amdgpu-y := amdgpu_drv.o
|
||||
|
||||
# add KMS driver
|
||||
@@ -60,7 +69,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
|
||||
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
|
||||
amdgpu_fw_attestation.o amdgpu_securedisplay.o \
|
||||
amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \
|
||||
amdgpu_ring_mux.o
|
||||
amdgpu_ring_mux.o amdgpu_xcp.o
|
||||
|
||||
amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
|
||||
|
||||
@@ -78,7 +87,7 @@ amdgpu-y += \
|
||||
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o arct_reg_init.o mxgpu_nv.o \
|
||||
nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o soc21.o \
|
||||
sienna_cichlid.o smu_v13_0_10.o nbio_v4_3.o hdp_v6_0.o nbio_v7_7.o hdp_v5_2.o lsdma_v6_0.o \
|
||||
nbio_v7_9.o
|
||||
nbio_v7_9.o aqua_vanjaram_reg_init.o
|
||||
|
||||
# add DF block
|
||||
amdgpu-y += \
|
||||
@@ -183,12 +192,14 @@ amdgpu-y += \
|
||||
vcn_v2_5.o \
|
||||
vcn_v3_0.o \
|
||||
vcn_v4_0.o \
|
||||
vcn_v4_0_3.o \
|
||||
amdgpu_jpeg.o \
|
||||
jpeg_v1_0.o \
|
||||
jpeg_v2_0.o \
|
||||
jpeg_v2_5.o \
|
||||
jpeg_v3_0.o \
|
||||
jpeg_v4_0.o
|
||||
jpeg_v4_0.o \
|
||||
jpeg_v4_0_3.o
|
||||
|
||||
# add ATHUB block
|
||||
amdgpu-y += \
|
||||
@@ -203,6 +214,7 @@ amdgpu-y += \
|
||||
smuio_v11_0.o \
|
||||
smuio_v11_0_6.o \
|
||||
smuio_v13_0.o \
|
||||
smuio_v13_0_3.o \
|
||||
smuio_v13_0_6.o
|
||||
|
||||
# add reset block
|
||||
@@ -228,6 +240,7 @@ amdgpu-y += \
|
||||
amdgpu_amdkfd_gfx_v9.o \
|
||||
amdgpu_amdkfd_arcturus.o \
|
||||
amdgpu_amdkfd_aldebaran.o \
|
||||
amdgpu_amdkfd_gc_9_4_3.o \
|
||||
amdgpu_amdkfd_gfx_v10.o \
|
||||
amdgpu_amdkfd_gfx_v10_3.o \
|
||||
amdgpu_amdkfd_gfx_v11.o
|
||||
|
||||
@@ -107,8 +107,9 @@
|
||||
#include "amdgpu_fdinfo.h"
|
||||
#include "amdgpu_mca.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_xcp.h"
|
||||
|
||||
#define MAX_GPU_INSTANCE 16
|
||||
#define MAX_GPU_INSTANCE 64
|
||||
|
||||
struct amdgpu_gpu_instance
|
||||
{
|
||||
@@ -212,6 +213,8 @@ extern int amdgpu_noretry;
|
||||
extern int amdgpu_force_asic_type;
|
||||
extern int amdgpu_smartshift_bias;
|
||||
extern int amdgpu_use_xgmi_p2p;
|
||||
extern int amdgpu_mtype_local;
|
||||
extern bool enforce_isolation;
|
||||
#ifdef CONFIG_HSA_AMD
|
||||
extern int sched_policy;
|
||||
extern bool debug_evictions;
|
||||
@@ -242,9 +245,10 @@ extern int amdgpu_num_kcq;
|
||||
extern int amdgpu_vcnfw_log;
|
||||
extern int amdgpu_sg_display;
|
||||
|
||||
extern int amdgpu_user_partt_mode;
|
||||
|
||||
#define AMDGPU_VM_MAX_NUM_CTX 4096
|
||||
#define AMDGPU_SG_THRESHOLD (256*1024*1024)
|
||||
#define AMDGPU_DEFAULT_GTT_SIZE_MB 3072ULL /* 3GB by default */
|
||||
#define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
|
||||
#define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */
|
||||
#define AMDGPU_FENCE_JIFFIES_TIMEOUT (HZ / 2)
|
||||
@@ -282,6 +286,7 @@ extern int amdgpu_sg_display;
|
||||
#define AMDGPU_SMARTSHIFT_MAX_BIAS (100)
|
||||
#define AMDGPU_SMARTSHIFT_MIN_BIAS (-100)
|
||||
|
||||
struct amdgpu_xcp_mgr;
|
||||
struct amdgpu_device;
|
||||
struct amdgpu_irq_src;
|
||||
struct amdgpu_fpriv;
|
||||
@@ -463,6 +468,8 @@ struct amdgpu_fpriv {
|
||||
struct mutex bo_list_lock;
|
||||
struct idr bo_list_handles;
|
||||
struct amdgpu_ctx_mgr ctx_mgr;
|
||||
/** GPU partition selection */
|
||||
uint32_t xcp_id;
|
||||
};
|
||||
|
||||
int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
|
||||
@@ -573,6 +580,8 @@ struct amdgpu_asic_funcs {
|
||||
/* query video codecs */
|
||||
int (*query_video_codecs)(struct amdgpu_device *adev, bool encode,
|
||||
const struct amdgpu_video_codecs **codecs);
|
||||
/* encode "> 32bits" smn addressing */
|
||||
u64 (*encode_ext_smn_addressing)(int ext_id);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -607,6 +616,9 @@ void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device);
|
||||
typedef uint32_t (*amdgpu_rreg_t)(struct amdgpu_device*, uint32_t);
|
||||
typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
|
||||
|
||||
typedef uint32_t (*amdgpu_rreg_ext_t)(struct amdgpu_device*, uint64_t);
|
||||
typedef void (*amdgpu_wreg_ext_t)(struct amdgpu_device*, uint64_t, uint32_t);
|
||||
|
||||
typedef uint64_t (*amdgpu_rreg64_t)(struct amdgpu_device*, uint32_t);
|
||||
typedef void (*amdgpu_wreg64_t)(struct amdgpu_device*, uint32_t, uint64_t);
|
||||
|
||||
@@ -657,7 +669,7 @@ enum amd_hw_ip_block_type {
|
||||
MAX_HWIP
|
||||
};
|
||||
|
||||
#define HWIP_MAX_INSTANCE 28
|
||||
#define HWIP_MAX_INSTANCE 44
|
||||
|
||||
#define HW_ID_MAX 300
|
||||
#define IP_VERSION(mj, mn, rv) (((mj) << 16) | ((mn) << 8) | (rv))
|
||||
@@ -665,6 +677,17 @@ enum amd_hw_ip_block_type {
|
||||
#define IP_VERSION_MIN(ver) (((ver) >> 8) & 0xFF)
|
||||
#define IP_VERSION_REV(ver) ((ver) & 0xFF)
|
||||
|
||||
struct amdgpu_ip_map_info {
|
||||
/* Map of logical to actual dev instances/mask */
|
||||
uint32_t dev_inst[MAX_HWIP][HWIP_MAX_INSTANCE];
|
||||
int8_t (*logical_to_dev_inst)(struct amdgpu_device *adev,
|
||||
enum amd_hw_ip_block_type block,
|
||||
int8_t inst);
|
||||
uint32_t (*logical_to_dev_mask)(struct amdgpu_device *adev,
|
||||
enum amd_hw_ip_block_type block,
|
||||
uint32_t mask);
|
||||
};
|
||||
|
||||
struct amd_powerplay {
|
||||
void *pp_handle;
|
||||
const struct amd_pm_funcs *pp_funcs;
|
||||
@@ -750,6 +773,7 @@ struct amdgpu_device {
|
||||
struct amdgpu_acp acp;
|
||||
#endif
|
||||
struct amdgpu_hive_info *hive;
|
||||
struct amdgpu_xcp_mgr *xcp_mgr;
|
||||
/* ASIC */
|
||||
enum amd_asic_type asic_type;
|
||||
uint32_t family;
|
||||
@@ -797,6 +821,8 @@ struct amdgpu_device {
|
||||
amdgpu_wreg_t pcie_wreg;
|
||||
amdgpu_rreg_t pciep_rreg;
|
||||
amdgpu_wreg_t pciep_wreg;
|
||||
amdgpu_rreg_ext_t pcie_rreg_ext;
|
||||
amdgpu_wreg_ext_t pcie_wreg_ext;
|
||||
amdgpu_rreg64_t pcie_rreg64;
|
||||
amdgpu_wreg64_t pcie_wreg64;
|
||||
/* protects concurrent UVD register access */
|
||||
@@ -830,7 +856,7 @@ struct amdgpu_device {
|
||||
dma_addr_t dummy_page_addr;
|
||||
struct amdgpu_vm_manager vm_manager;
|
||||
struct amdgpu_vmhub vmhub[AMDGPU_MAX_VMHUBS];
|
||||
unsigned num_vmhubs;
|
||||
DECLARE_BITMAP(vmhubs_mask, AMDGPU_MAX_VMHUBS);
|
||||
|
||||
/* memory management */
|
||||
struct amdgpu_mman mman;
|
||||
@@ -962,6 +988,7 @@ struct amdgpu_device {
|
||||
|
||||
/* soc15 register offset based on ip, instance and segment */
|
||||
uint32_t *reg_offset[MAX_HWIP][HWIP_MAX_INSTANCE];
|
||||
struct amdgpu_ip_map_info ip_map;
|
||||
|
||||
/* delayed work_func for deferring clockgating during resume */
|
||||
struct delayed_work delayed_init_work;
|
||||
@@ -1020,6 +1047,9 @@ struct amdgpu_device {
|
||||
struct pci_saved_state *pci_state;
|
||||
pci_channel_state_t pci_channel_state;
|
||||
|
||||
/* Track auto wait count on s_barrier settings */
|
||||
bool barrier_has_auto_waitcnt;
|
||||
|
||||
struct amdgpu_reset_control *reset_cntl;
|
||||
uint32_t ip_versions[MAX_HWIP][HWIP_MAX_INSTANCE];
|
||||
|
||||
@@ -1050,6 +1080,8 @@ struct amdgpu_device {
|
||||
|
||||
bool job_hang;
|
||||
bool dc_enabled;
|
||||
/* Mask of active clusters */
|
||||
uint32_t aid_mask;
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
|
||||
@@ -1081,11 +1113,18 @@ size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos,
|
||||
|
||||
void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
void *buf, size_t size, bool write);
|
||||
uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev,
|
||||
uint32_t inst, uint32_t reg_addr, char reg_name[],
|
||||
uint32_t expected_value, uint32_t mask);
|
||||
uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t acc_flags);
|
||||
u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev,
|
||||
u64 reg_addr);
|
||||
void amdgpu_device_wreg(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags);
|
||||
void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev,
|
||||
u64 reg_addr, u32 reg_data);
|
||||
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v);
|
||||
void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value);
|
||||
@@ -1137,6 +1176,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
#define WREG32_PCIE(reg, v) adev->pcie_wreg(adev, (reg), (v))
|
||||
#define RREG32_PCIE_PORT(reg) adev->pciep_rreg(adev, (reg))
|
||||
#define WREG32_PCIE_PORT(reg, v) adev->pciep_wreg(adev, (reg), (v))
|
||||
#define RREG32_PCIE_EXT(reg) adev->pcie_rreg_ext(adev, (reg))
|
||||
#define WREG32_PCIE_EXT(reg, v) adev->pcie_wreg_ext(adev, (reg), (v))
|
||||
#define RREG64_PCIE(reg) adev->pcie_rreg64(adev, (reg))
|
||||
#define WREG64_PCIE(reg, v) adev->pcie_wreg64(adev, (reg), (v))
|
||||
#define RREG32_SMC(reg) adev->smc_rreg(adev, (reg))
|
||||
@@ -1204,7 +1245,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
/*
|
||||
* ASICs macro.
|
||||
*/
|
||||
#define amdgpu_asic_set_vga_state(adev, state) (adev)->asic_funcs->set_vga_state((adev), (state))
|
||||
#define amdgpu_asic_set_vga_state(adev, state) \
|
||||
((adev)->asic_funcs->set_vga_state ? (adev)->asic_funcs->set_vga_state((adev), (state)) : 0)
|
||||
#define amdgpu_asic_reset(adev) (adev)->asic_funcs->reset((adev))
|
||||
#define amdgpu_asic_reset_method(adev) (adev)->asic_funcs->reset_method((adev))
|
||||
#define amdgpu_asic_get_xclk(adev) (adev)->asic_funcs->get_xclk((adev))
|
||||
@@ -1235,6 +1277,10 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
|
||||
#define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter));
|
||||
|
||||
#define for_each_inst(i, inst_mask) \
|
||||
for (i = ffs(inst_mask) - 1; inst_mask; \
|
||||
inst_mask &= ~(1U << i), i = ffs(inst_mask) - 1)
|
||||
|
||||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
|
||||
/* Common functions */
|
||||
@@ -1348,6 +1394,12 @@ struct amdgpu_afmt_acr amdgpu_afmt_acr(uint32_t clock);
|
||||
|
||||
/* amdgpu_acpi.c */
|
||||
|
||||
struct amdgpu_numa_info {
|
||||
uint64_t size;
|
||||
int pxm;
|
||||
int nid;
|
||||
};
|
||||
|
||||
/* ATCS Device/Driver State */
|
||||
#define AMDGPU_ATCS_PSC_DEV_STATE_D0 0
|
||||
#define AMDGPU_ATCS_PSC_DEV_STATE_D3_HOT 3
|
||||
@@ -1365,15 +1417,32 @@ int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
|
||||
u8 dev_state, bool drv_state);
|
||||
int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_state);
|
||||
int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
|
||||
int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, u64 *tmr_offset,
|
||||
u64 *tmr_size);
|
||||
int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, int xcc_id,
|
||||
struct amdgpu_numa_info *numa_info);
|
||||
|
||||
void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps);
|
||||
bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev);
|
||||
void amdgpu_acpi_detect(void);
|
||||
void amdgpu_acpi_release(void);
|
||||
#else
|
||||
static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
|
||||
static inline int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev,
|
||||
u64 *tmr_offset, u64 *tmr_size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev,
|
||||
int xcc_id,
|
||||
struct amdgpu_numa_info *numa_info)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
|
||||
static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; }
|
||||
static inline void amdgpu_acpi_detect(void) { }
|
||||
static inline void amdgpu_acpi_release(void) { }
|
||||
static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; }
|
||||
static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
|
||||
u8 dev_state, bool drv_state) { return 0; }
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/xarray.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/suspend.h>
|
||||
@@ -38,6 +39,45 @@
|
||||
#include "amd_acpi.h"
|
||||
#include "atom.h"
|
||||
|
||||
/* Declare GUID for AMD _DSM method for XCCs */
|
||||
static const guid_t amd_xcc_dsm_guid = GUID_INIT(0x8267f5d5, 0xa556, 0x44f2,
|
||||
0xb8, 0xb4, 0x45, 0x56, 0x2e,
|
||||
0x8c, 0x5b, 0xec);
|
||||
|
||||
#define AMD_XCC_HID_START 3000
|
||||
#define AMD_XCC_DSM_GET_NUM_FUNCS 0
|
||||
#define AMD_XCC_DSM_GET_SUPP_MODE 1
|
||||
#define AMD_XCC_DSM_GET_XCP_MODE 2
|
||||
#define AMD_XCC_DSM_GET_VF_XCC_MAPPING 4
|
||||
#define AMD_XCC_DSM_GET_TMR_INFO 5
|
||||
#define AMD_XCC_DSM_NUM_FUNCS 5
|
||||
|
||||
#define AMD_XCC_MAX_HID 24
|
||||
|
||||
struct xarray numa_info_xa;
|
||||
|
||||
/* Encapsulates the XCD acpi object information */
|
||||
struct amdgpu_acpi_xcc_info {
|
||||
struct list_head list;
|
||||
struct amdgpu_numa_info *numa_info;
|
||||
uint8_t xcp_node;
|
||||
uint8_t phy_id;
|
||||
acpi_handle handle;
|
||||
};
|
||||
|
||||
struct amdgpu_acpi_dev_info {
|
||||
struct list_head list;
|
||||
struct list_head xcc_list;
|
||||
uint16_t bdf;
|
||||
uint16_t supp_xcp_mode;
|
||||
uint16_t xcp_mode;
|
||||
uint16_t mem_mode;
|
||||
uint64_t tmr_base;
|
||||
uint64_t tmr_size;
|
||||
};
|
||||
|
||||
struct list_head amdgpu_acpi_dev_list;
|
||||
|
||||
struct amdgpu_atif_notification_cfg {
|
||||
bool enabled;
|
||||
int command_code;
|
||||
@@ -801,6 +841,343 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_NUMA
|
||||
static inline uint64_t amdgpu_acpi_get_numa_size(int nid)
|
||||
{
|
||||
/* This is directly using si_meminfo_node implementation as the
|
||||
* function is not exported.
|
||||
*/
|
||||
int zone_type;
|
||||
uint64_t managed_pages = 0;
|
||||
|
||||
pg_data_t *pgdat = NODE_DATA(nid);
|
||||
|
||||
for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++)
|
||||
managed_pages +=
|
||||
zone_managed_pages(&pgdat->node_zones[zone_type]);
|
||||
return managed_pages * PAGE_SIZE;
|
||||
}
|
||||
|
||||
static struct amdgpu_numa_info *amdgpu_acpi_get_numa_info(uint32_t pxm)
|
||||
{
|
||||
struct amdgpu_numa_info *numa_info;
|
||||
int nid;
|
||||
|
||||
numa_info = xa_load(&numa_info_xa, pxm);
|
||||
|
||||
if (!numa_info) {
|
||||
struct sysinfo info;
|
||||
|
||||
numa_info = kzalloc(sizeof *numa_info, GFP_KERNEL);
|
||||
if (!numa_info)
|
||||
return NULL;
|
||||
|
||||
nid = pxm_to_node(pxm);
|
||||
numa_info->pxm = pxm;
|
||||
numa_info->nid = nid;
|
||||
|
||||
if (numa_info->nid == NUMA_NO_NODE) {
|
||||
si_meminfo(&info);
|
||||
numa_info->size = info.totalram * info.mem_unit;
|
||||
} else {
|
||||
numa_info->size = amdgpu_acpi_get_numa_size(nid);
|
||||
}
|
||||
xa_store(&numa_info_xa, numa_info->pxm, numa_info, GFP_KERNEL);
|
||||
}
|
||||
|
||||
return numa_info;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* amdgpu_acpi_get_node_id - obtain the NUMA node id for corresponding amdgpu
|
||||
* acpi device handle
|
||||
*
|
||||
* @handle: acpi handle
|
||||
* @numa_info: amdgpu_numa_info structure holding numa information
|
||||
*
|
||||
* Queries the ACPI interface to fetch the corresponding NUMA Node ID for a
|
||||
* given amdgpu acpi device.
|
||||
*
|
||||
* Returns ACPI STATUS OK with Node ID on success or the corresponding failure reason
|
||||
*/
|
||||
static acpi_status amdgpu_acpi_get_node_id(acpi_handle handle,
|
||||
struct amdgpu_numa_info **numa_info)
|
||||
{
|
||||
#ifdef CONFIG_ACPI_NUMA
|
||||
u64 pxm;
|
||||
acpi_status status;
|
||||
|
||||
if (!numa_info)
|
||||
return_ACPI_STATUS(AE_ERROR);
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
return status;
|
||||
|
||||
*numa_info = amdgpu_acpi_get_numa_info(pxm);
|
||||
|
||||
if (!*numa_info)
|
||||
return_ACPI_STATUS(AE_ERROR);
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
#else
|
||||
return_ACPI_STATUS(AE_NOT_EXIST);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct amdgpu_acpi_dev_info *amdgpu_acpi_get_dev(u16 bdf)
|
||||
{
|
||||
struct amdgpu_acpi_dev_info *acpi_dev;
|
||||
|
||||
if (list_empty(&amdgpu_acpi_dev_list))
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(acpi_dev, &amdgpu_acpi_dev_list, list)
|
||||
if (acpi_dev->bdf == bdf)
|
||||
return acpi_dev;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int amdgpu_acpi_dev_init(struct amdgpu_acpi_dev_info **dev_info,
|
||||
struct amdgpu_acpi_xcc_info *xcc_info, u16 bdf)
|
||||
{
|
||||
struct amdgpu_acpi_dev_info *tmp;
|
||||
union acpi_object *obj;
|
||||
int ret = -ENOENT;
|
||||
|
||||
*dev_info = NULL;
|
||||
tmp = kzalloc(sizeof(struct amdgpu_acpi_dev_info), GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&tmp->xcc_list);
|
||||
INIT_LIST_HEAD(&tmp->list);
|
||||
tmp->bdf = bdf;
|
||||
|
||||
obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
|
||||
AMD_XCC_DSM_GET_SUPP_MODE, NULL,
|
||||
ACPI_TYPE_INTEGER);
|
||||
|
||||
if (!obj) {
|
||||
acpi_handle_debug(xcc_info->handle,
|
||||
"_DSM function %d evaluation failed",
|
||||
AMD_XCC_DSM_GET_SUPP_MODE);
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp->supp_xcp_mode = obj->integer.value & 0xFFFF;
|
||||
ACPI_FREE(obj);
|
||||
|
||||
obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
|
||||
AMD_XCC_DSM_GET_XCP_MODE, NULL,
|
||||
ACPI_TYPE_INTEGER);
|
||||
|
||||
if (!obj) {
|
||||
acpi_handle_debug(xcc_info->handle,
|
||||
"_DSM function %d evaluation failed",
|
||||
AMD_XCC_DSM_GET_XCP_MODE);
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp->xcp_mode = obj->integer.value & 0xFFFF;
|
||||
tmp->mem_mode = (obj->integer.value >> 32) & 0xFFFF;
|
||||
ACPI_FREE(obj);
|
||||
|
||||
/* Evaluate DSMs and fill XCC information */
|
||||
obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
|
||||
AMD_XCC_DSM_GET_TMR_INFO, NULL,
|
||||
ACPI_TYPE_PACKAGE);
|
||||
|
||||
if (!obj || obj->package.count < 2) {
|
||||
acpi_handle_debug(xcc_info->handle,
|
||||
"_DSM function %d evaluation failed",
|
||||
AMD_XCC_DSM_GET_TMR_INFO);
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp->tmr_base = obj->package.elements[0].integer.value;
|
||||
tmp->tmr_size = obj->package.elements[1].integer.value;
|
||||
ACPI_FREE(obj);
|
||||
|
||||
DRM_DEBUG_DRIVER(
|
||||
"New dev(%x): Supported xcp mode: %x curr xcp_mode : %x mem mode : %x, tmr base: %llx tmr size: %llx ",
|
||||
tmp->bdf, tmp->supp_xcp_mode, tmp->xcp_mode, tmp->mem_mode,
|
||||
tmp->tmr_base, tmp->tmr_size);
|
||||
list_add_tail(&tmp->list, &amdgpu_acpi_dev_list);
|
||||
*dev_info = tmp;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
if (obj)
|
||||
ACPI_FREE(obj);
|
||||
kfree(tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amdgpu_acpi_get_xcc_info(struct amdgpu_acpi_xcc_info *xcc_info,
|
||||
u16 *bdf)
|
||||
{
|
||||
union acpi_object *obj;
|
||||
acpi_status status;
|
||||
int ret = -ENOENT;
|
||||
|
||||
obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
|
||||
AMD_XCC_DSM_GET_NUM_FUNCS, NULL,
|
||||
ACPI_TYPE_INTEGER);
|
||||
|
||||
if (!obj || obj->integer.value != AMD_XCC_DSM_NUM_FUNCS)
|
||||
goto out;
|
||||
ACPI_FREE(obj);
|
||||
|
||||
/* Evaluate DSMs and fill XCC information */
|
||||
obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
|
||||
AMD_XCC_DSM_GET_VF_XCC_MAPPING, NULL,
|
||||
ACPI_TYPE_INTEGER);
|
||||
|
||||
if (!obj) {
|
||||
acpi_handle_debug(xcc_info->handle,
|
||||
"_DSM function %d evaluation failed",
|
||||
AMD_XCC_DSM_GET_VF_XCC_MAPPING);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* PF xcc id [39:32] */
|
||||
xcc_info->phy_id = (obj->integer.value >> 32) & 0xFF;
|
||||
/* xcp node of this xcc [47:40] */
|
||||
xcc_info->xcp_node = (obj->integer.value >> 40) & 0xFF;
|
||||
/* PF bus/dev/fn of this xcc [63:48] */
|
||||
*bdf = (obj->integer.value >> 48) & 0xFFFF;
|
||||
ACPI_FREE(obj);
|
||||
obj = NULL;
|
||||
|
||||
status =
|
||||
amdgpu_acpi_get_node_id(xcc_info->handle, &xcc_info->numa_info);
|
||||
|
||||
/* TODO: check if this check is required */
|
||||
if (ACPI_SUCCESS(status))
|
||||
ret = 0;
|
||||
out:
|
||||
if (obj)
|
||||
ACPI_FREE(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amdgpu_acpi_enumerate_xcc(void)
|
||||
{
|
||||
struct amdgpu_acpi_dev_info *dev_info = NULL;
|
||||
struct amdgpu_acpi_xcc_info *xcc_info;
|
||||
struct acpi_device *acpi_dev;
|
||||
char hid[ACPI_ID_LEN];
|
||||
int ret, id;
|
||||
u16 bdf;
|
||||
|
||||
INIT_LIST_HEAD(&amdgpu_acpi_dev_list);
|
||||
xa_init(&numa_info_xa);
|
||||
|
||||
for (id = 0; id < AMD_XCC_MAX_HID; id++) {
|
||||
sprintf(hid, "%s%d", "AMD", AMD_XCC_HID_START + id);
|
||||
acpi_dev = acpi_dev_get_first_match_dev(hid, NULL, -1);
|
||||
/* These ACPI objects are expected to be in sequential order. If
|
||||
* one is not found, no need to check the rest.
|
||||
*/
|
||||
if (!acpi_dev) {
|
||||
DRM_DEBUG_DRIVER("No matching acpi device found for %s",
|
||||
hid);
|
||||
break;
|
||||
}
|
||||
|
||||
xcc_info = kzalloc(sizeof(struct amdgpu_acpi_xcc_info),
|
||||
GFP_KERNEL);
|
||||
if (!xcc_info) {
|
||||
DRM_ERROR("Failed to allocate memory for xcc info\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&xcc_info->list);
|
||||
xcc_info->handle = acpi_device_handle(acpi_dev);
|
||||
acpi_dev_put(acpi_dev);
|
||||
|
||||
ret = amdgpu_acpi_get_xcc_info(xcc_info, &bdf);
|
||||
if (ret) {
|
||||
kfree(xcc_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
dev_info = amdgpu_acpi_get_dev(bdf);
|
||||
|
||||
if (!dev_info)
|
||||
ret = amdgpu_acpi_dev_init(&dev_info, xcc_info, bdf);
|
||||
|
||||
if (ret == -ENOMEM)
|
||||
return ret;
|
||||
|
||||
if (!dev_info) {
|
||||
kfree(xcc_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
list_add_tail(&xcc_info->list, &dev_info->xcc_list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, u64 *tmr_offset,
|
||||
u64 *tmr_size)
|
||||
{
|
||||
struct amdgpu_acpi_dev_info *dev_info;
|
||||
u16 bdf;
|
||||
|
||||
if (!tmr_offset || !tmr_size)
|
||||
return -EINVAL;
|
||||
|
||||
bdf = (adev->pdev->bus->number << 8) | adev->pdev->devfn;
|
||||
dev_info = amdgpu_acpi_get_dev(bdf);
|
||||
if (!dev_info)
|
||||
return -ENOENT;
|
||||
|
||||
*tmr_offset = dev_info->tmr_base;
|
||||
*tmr_size = dev_info->tmr_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, int xcc_id,
|
||||
struct amdgpu_numa_info *numa_info)
|
||||
{
|
||||
struct amdgpu_acpi_dev_info *dev_info;
|
||||
struct amdgpu_acpi_xcc_info *xcc_info;
|
||||
u16 bdf;
|
||||
|
||||
if (!numa_info)
|
||||
return -EINVAL;
|
||||
|
||||
bdf = (adev->pdev->bus->number << 8) | adev->pdev->devfn;
|
||||
dev_info = amdgpu_acpi_get_dev(bdf);
|
||||
if (!dev_info)
|
||||
return -ENOENT;
|
||||
|
||||
list_for_each_entry(xcc_info, &dev_info->xcc_list, list) {
|
||||
if (xcc_info->phy_id == xcc_id) {
|
||||
memcpy(numa_info, xcc_info->numa_info,
|
||||
sizeof(*numa_info));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_acpi_event - handle notify events
|
||||
*
|
||||
@@ -1054,6 +1431,36 @@ void amdgpu_acpi_detect(void)
|
||||
} else {
|
||||
atif->backlight_caps.caps_valid = false;
|
||||
}
|
||||
|
||||
amdgpu_acpi_enumerate_xcc();
|
||||
}
|
||||
|
||||
void amdgpu_acpi_release(void)
|
||||
{
|
||||
struct amdgpu_acpi_dev_info *dev_info, *dev_tmp;
|
||||
struct amdgpu_acpi_xcc_info *xcc_info, *xcc_tmp;
|
||||
struct amdgpu_numa_info *numa_info;
|
||||
unsigned long index;
|
||||
|
||||
xa_for_each(&numa_info_xa, index, numa_info) {
|
||||
kfree(numa_info);
|
||||
xa_erase(&numa_info_xa, index);
|
||||
}
|
||||
|
||||
if (list_empty(&amdgpu_acpi_dev_list))
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(dev_info, dev_tmp, &amdgpu_acpi_dev_list,
|
||||
list) {
|
||||
list_for_each_entry_safe(xcc_info, xcc_tmp, &dev_info->xcc_list,
|
||||
list) {
|
||||
list_del(&xcc_info->list);
|
||||
kfree(xcc_info);
|
||||
}
|
||||
|
||||
list_del(&dev_info->list);
|
||||
kfree(dev_info);
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUSPEND)
|
||||
@@ -1092,16 +1499,20 @@ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
|
||||
* S0ix even though the system is suspending to idle, so return false
|
||||
* in that case.
|
||||
*/
|
||||
if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
|
||||
dev_warn_once(adev->dev,
|
||||
if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) {
|
||||
dev_err_once(adev->dev,
|
||||
"Power consumption will be higher as BIOS has not been configured for suspend-to-idle.\n"
|
||||
"To use suspend-to-idle change the sleep mode in BIOS setup.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !IS_ENABLED(CONFIG_AMD_PMC)
|
||||
dev_warn_once(adev->dev,
|
||||
dev_err_once(adev->dev,
|
||||
"Power consumption will be higher as the kernel has not been compiled with CONFIG_AMD_PMC.\n");
|
||||
#endif /* CONFIG_AMD_PMC */
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif /* CONFIG_AMD_PMC */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
@@ -53,7 +53,6 @@ int amdgpu_amdkfd_init(void)
|
||||
amdgpu_amdkfd_total_mem_size *= si.mem_unit;
|
||||
|
||||
ret = kgd2kfd_init();
|
||||
amdgpu_amdkfd_gpuvm_init_mem_limits();
|
||||
kfd_initialized = !ret;
|
||||
|
||||
return ret;
|
||||
@@ -143,6 +142,8 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
|
||||
int i;
|
||||
int last_valid_bit;
|
||||
|
||||
amdgpu_amdkfd_gpuvm_init_mem_limits();
|
||||
|
||||
if (adev->kfd.dev) {
|
||||
struct kgd2kfd_shared_resources gpu_resources = {
|
||||
.compute_vmid_bitmap =
|
||||
@@ -162,7 +163,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
|
||||
* clear
|
||||
*/
|
||||
bitmap_complement(gpu_resources.cp_queue_bitmap,
|
||||
adev->gfx.mec.queue_bitmap,
|
||||
adev->gfx.mec_bitmap[0].queue_bitmap,
|
||||
KGD_MAX_QUEUES);
|
||||
|
||||
/* According to linux/bitmap.h we shouldn't use bitmap_clear if
|
||||
@@ -427,14 +428,23 @@ uint32_t amdgpu_amdkfd_get_fw_version(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev,
|
||||
struct kfd_local_mem_info *mem_info)
|
||||
struct kfd_local_mem_info *mem_info,
|
||||
struct amdgpu_xcp *xcp)
|
||||
{
|
||||
memset(mem_info, 0, sizeof(*mem_info));
|
||||
|
||||
mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
|
||||
mem_info->local_mem_size_private = adev->gmc.real_vram_size -
|
||||
if (xcp) {
|
||||
if (adev->gmc.real_vram_size == adev->gmc.visible_vram_size)
|
||||
mem_info->local_mem_size_public =
|
||||
KFD_XCP_MEMORY_SIZE(adev, xcp->id);
|
||||
else
|
||||
mem_info->local_mem_size_private =
|
||||
KFD_XCP_MEMORY_SIZE(adev, xcp->id);
|
||||
} else {
|
||||
mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
|
||||
mem_info->local_mem_size_private = adev->gmc.real_vram_size -
|
||||
adev->gmc.visible_vram_size;
|
||||
|
||||
}
|
||||
mem_info->vram_width = adev->gmc.vram_width;
|
||||
|
||||
pr_debug("Address base: %pap public 0x%llx private 0x%llx\n",
|
||||
@@ -497,7 +507,7 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||
struct amdgpu_device **dmabuf_adev,
|
||||
uint64_t *bo_size, void *metadata_buffer,
|
||||
size_t buffer_size, uint32_t *metadata_size,
|
||||
uint32_t *flags)
|
||||
uint32_t *flags, int8_t *xcp_id)
|
||||
{
|
||||
struct dma_buf *dma_buf;
|
||||
struct drm_gem_object *obj;
|
||||
@@ -541,6 +551,8 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||
if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
|
||||
*flags |= KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC;
|
||||
}
|
||||
if (xcp_id)
|
||||
*xcp_id = bo->xcp_id;
|
||||
|
||||
out_put:
|
||||
dma_buf_put(dma_buf);
|
||||
@@ -732,17 +744,19 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev,
|
||||
if (adev->family == AMDGPU_FAMILY_AI) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->num_vmhubs; i++)
|
||||
for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
|
||||
amdgpu_gmc_flush_gpu_tlb(adev, vmid, i, 0);
|
||||
} else {
|
||||
amdgpu_gmc_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB_0, 0);
|
||||
amdgpu_gmc_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB(0), 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
uint16_t pasid, enum TLB_FLUSH_TYPE flush_type)
|
||||
uint16_t pasid,
|
||||
enum TLB_FLUSH_TYPE flush_type,
|
||||
uint32_t inst)
|
||||
{
|
||||
bool all_hub = false;
|
||||
|
||||
@@ -750,7 +764,7 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
adev->family == AMDGPU_FAMILY_RV)
|
||||
all_hub = true;
|
||||
|
||||
return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub);
|
||||
return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub, inst);
|
||||
}
|
||||
|
||||
bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev)
|
||||
@@ -758,11 +772,32 @@ bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev)
|
||||
return adev->have_atomics_support;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_debug_mem_fence(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_device_flush_hdp(adev, NULL);
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset)
|
||||
{
|
||||
amdgpu_umc_poison_handler(adev, reset);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev,
|
||||
uint32_t *payload)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Device or IH ring is not ready so bail. */
|
||||
ret = amdgpu_ih_wait_on_checkpoint_process_ts(adev, &adev->irq.ih);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Send payload to fence KFD interrupts */
|
||||
amdgpu_amdkfd_interrupt(adev, payload);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->gfx.ras && adev->gfx.ras->query_utcl2_poison_status)
|
||||
@@ -770,3 +805,28 @@ bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev)
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_check_and_lock_kfd(struct amdgpu_device *adev)
|
||||
{
|
||||
return kgd2kfd_check_and_lock_kfd();
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_unlock_kfd(struct amdgpu_device *adev)
|
||||
{
|
||||
kgd2kfd_unlock_kfd();
|
||||
}
|
||||
|
||||
|
||||
u64 amdgpu_amdkfd_xcp_memory_size(struct amdgpu_device *adev, int xcp_id)
|
||||
{
|
||||
u64 tmp;
|
||||
s8 mem_id = KFD_XCP_MEM_ID(adev, xcp_id);
|
||||
|
||||
if (adev->gmc.num_mem_partitions && xcp_id >= 0 && mem_id >= 0) {
|
||||
tmp = adev->gmc.mem_partitions[mem_id].size;
|
||||
do_div(tmp, adev->xcp_mgr->num_xcp_per_mem_partition);
|
||||
return ALIGN_DOWN(tmp, PAGE_SIZE);
|
||||
} else {
|
||||
return adev->gmc.real_vram_size;
|
||||
}
|
||||
}
|
||||
@@ -30,10 +30,12 @@
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
#include <linux/memremap.h>
|
||||
#include <kgd_kfd_interface.h>
|
||||
#include <drm/ttm/ttm_execbuf_util.h>
|
||||
#include "amdgpu_sync.h"
|
||||
#include "amdgpu_vm.h"
|
||||
#include "amdgpu_xcp.h"
|
||||
|
||||
extern uint64_t amdgpu_amdkfd_total_mem_size;
|
||||
|
||||
@@ -97,10 +99,13 @@ struct amdgpu_amdkfd_fence {
|
||||
|
||||
struct amdgpu_kfd_dev {
|
||||
struct kfd_dev *dev;
|
||||
int64_t vram_used;
|
||||
uint64_t vram_used_aligned;
|
||||
int64_t vram_used[MAX_XCP];
|
||||
uint64_t vram_used_aligned[MAX_XCP];
|
||||
bool init_complete;
|
||||
struct work_struct reset_work;
|
||||
|
||||
/* HMM page migration MEMORY_DEVICE_PRIVATE mapping */
|
||||
struct dev_pagemap pgmap;
|
||||
};
|
||||
|
||||
enum kgd_engine_type {
|
||||
@@ -151,6 +156,8 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
|
||||
void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_init(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_fini_sw(struct amdgpu_device *adev);
|
||||
int amdgpu_amdkfd_check_and_lock_kfd(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_unlock_kfd(struct amdgpu_device *adev);
|
||||
int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
|
||||
enum kgd_engine_type engine,
|
||||
uint32_t vmid, uint64_t gpu_addr,
|
||||
@@ -160,7 +167,8 @@ bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev);
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev,
|
||||
uint16_t vmid);
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
uint16_t pasid, enum TLB_FLUSH_TYPE flush_type);
|
||||
uint16_t pasid, enum TLB_FLUSH_TYPE flush_type,
|
||||
uint32_t inst);
|
||||
|
||||
bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid);
|
||||
|
||||
@@ -224,7 +232,8 @@ int amdgpu_amdkfd_remove_gws_from_process(void *info, void *mem);
|
||||
uint32_t amdgpu_amdkfd_get_fw_version(struct amdgpu_device *adev,
|
||||
enum kgd_engine_type type);
|
||||
void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev,
|
||||
struct kfd_local_mem_info *mem_info);
|
||||
struct kfd_local_mem_info *mem_info,
|
||||
struct amdgpu_xcp *xcp);
|
||||
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev);
|
||||
|
||||
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev);
|
||||
@@ -234,13 +243,15 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||
struct amdgpu_device **dmabuf_adev,
|
||||
uint64_t *bo_size, void *metadata_buffer,
|
||||
size_t buffer_size, uint32_t *metadata_size,
|
||||
uint32_t *flags);
|
||||
uint32_t *flags, int8_t *xcp_id);
|
||||
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src);
|
||||
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src,
|
||||
bool is_min);
|
||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min);
|
||||
int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev,
|
||||
uint32_t *payload);
|
||||
|
||||
/* Read user wptr from a specified user address space with page fault
|
||||
* disabled. The memory must be pinned and mapped to the hardware when
|
||||
@@ -279,7 +290,8 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev,
|
||||
void *drm_priv);
|
||||
uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv);
|
||||
size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev);
|
||||
size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev,
|
||||
uint8_t xcp_id);
|
||||
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
struct amdgpu_device *adev, uint64_t va, uint64_t size,
|
||||
void *drm_priv, struct kgd_mem **mem,
|
||||
@@ -310,6 +322,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
|
||||
uint64_t *mmap_offset);
|
||||
int amdgpu_amdkfd_gpuvm_export_dmabuf(struct kgd_mem *mem,
|
||||
struct dma_buf **dmabuf);
|
||||
void amdgpu_amdkfd_debug_mem_fence(struct amdgpu_device *adev);
|
||||
int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev,
|
||||
struct tile_config *config);
|
||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
@@ -319,9 +332,18 @@ void amdgpu_amdkfd_block_mmu_notifications(void *p);
|
||||
int amdgpu_amdkfd_criu_resume(void *p);
|
||||
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev);
|
||||
int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
||||
uint64_t size, u32 alloc_flag);
|
||||
uint64_t size, u32 alloc_flag, int8_t xcp_id);
|
||||
void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
|
||||
uint64_t size, u32 alloc_flag);
|
||||
uint64_t size, u32 alloc_flag, int8_t xcp_id);
|
||||
|
||||
u64 amdgpu_amdkfd_xcp_memory_size(struct amdgpu_device *adev, int xcp_id);
|
||||
|
||||
#define KFD_XCP_MEM_ID(adev, xcp_id) \
|
||||
((adev)->xcp_mgr && (xcp_id) >= 0 ?\
|
||||
(adev)->xcp_mgr->xcp[(xcp_id)].mem_id : -1)
|
||||
|
||||
#define KFD_XCP_MEMORY_SIZE(adev, xcp_id) amdgpu_amdkfd_xcp_memory_size((adev), (xcp_id))
|
||||
|
||||
|
||||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
|
||||
@@ -352,6 +374,17 @@ void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
|
||||
int kgd2kfd_init_zone_device(struct amdgpu_device *adev);
|
||||
#else
|
||||
static inline
|
||||
int kgd2kfd_init_zone_device(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* KGD2KFD callbacks */
|
||||
int kgd2kfd_quiesce_mm(struct mm_struct *mm, uint32_t trigger);
|
||||
int kgd2kfd_resume_mm(struct mm_struct *mm);
|
||||
@@ -372,6 +405,8 @@ int kgd2kfd_post_reset(struct kfd_dev *kfd);
|
||||
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry);
|
||||
void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd);
|
||||
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask);
|
||||
int kgd2kfd_check_and_lock_kfd(void);
|
||||
void kgd2kfd_unlock_kfd(void);
|
||||
#else
|
||||
static inline int kgd2kfd_init(void)
|
||||
{
|
||||
@@ -437,5 +472,14 @@ static inline
|
||||
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int kgd2kfd_check_and_lock_kfd(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void kgd2kfd_unlock_kfd(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif /* AMDGPU_AMDKFD_H_INCLUDED */
|
||||
@@ -23,6 +23,149 @@
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_amdkfd_arcturus.h"
|
||||
#include "amdgpu_amdkfd_gfx_v9.h"
|
||||
#include "gc/gc_9_4_2_offset.h"
|
||||
#include "gc/gc_9_4_2_sh_mask.h"
|
||||
#include <uapi/linux/kfd_ioctl.h>
|
||||
|
||||
/*
|
||||
* Returns TRAP_EN, EXCP_EN and EXCP_REPLACE.
|
||||
*
|
||||
* restore_dbg_registers is ignored here but is a general interface requirement
|
||||
* for devices that support GFXOFF and where the RLC save/restore list
|
||||
* does not support hw registers for debugging i.e. the driver has to manually
|
||||
* initialize the debug mode registers after it has disabled GFX off during the
|
||||
* debug session.
|
||||
*/
|
||||
static uint32_t kgd_aldebaran_enable_debug_trap(struct amdgpu_device *adev,
|
||||
bool restore_dbg_registers,
|
||||
uint32_t vmid)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, 0);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, 0);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* returns TRAP_EN, EXCP_EN and EXCP_REPLACE. */
|
||||
static uint32_t kgd_aldebaran_disable_debug_trap(struct amdgpu_device *adev,
|
||||
bool keep_trap_enabled,
|
||||
uint32_t vmid)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, keep_trap_enabled);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, 0);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, 0);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static int kgd_aldebaran_validate_trap_override_request(struct amdgpu_device *adev,
|
||||
uint32_t trap_override,
|
||||
uint32_t *trap_mask_supported)
|
||||
{
|
||||
*trap_mask_supported &= KFD_DBG_TRAP_MASK_FP_INVALID |
|
||||
KFD_DBG_TRAP_MASK_FP_INPUT_DENORMAL |
|
||||
KFD_DBG_TRAP_MASK_FP_DIVIDE_BY_ZERO |
|
||||
KFD_DBG_TRAP_MASK_FP_OVERFLOW |
|
||||
KFD_DBG_TRAP_MASK_FP_UNDERFLOW |
|
||||
KFD_DBG_TRAP_MASK_FP_INEXACT |
|
||||
KFD_DBG_TRAP_MASK_INT_DIVIDE_BY_ZERO |
|
||||
KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH |
|
||||
KFD_DBG_TRAP_MASK_DBG_MEMORY_VIOLATION;
|
||||
|
||||
if (trap_override != KFD_DBG_TRAP_OVERRIDE_OR &&
|
||||
trap_override != KFD_DBG_TRAP_OVERRIDE_REPLACE)
|
||||
return -EPERM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns TRAP_EN, EXCP_EN and EXCP_RPLACE. */
|
||||
static uint32_t kgd_aldebaran_set_wave_launch_trap_override(struct amdgpu_device *adev,
|
||||
uint32_t vmid,
|
||||
uint32_t trap_override,
|
||||
uint32_t trap_mask_bits,
|
||||
uint32_t trap_mask_request,
|
||||
uint32_t *trap_mask_prev,
|
||||
uint32_t kfd_dbg_trap_cntl_prev)
|
||||
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
*trap_mask_prev = REG_GET_FIELD(kfd_dbg_trap_cntl_prev, SPI_GDBG_PER_VMID_CNTL, EXCP_EN);
|
||||
trap_mask_bits = (trap_mask_bits & trap_mask_request) |
|
||||
(*trap_mask_prev & ~trap_mask_request);
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, trap_mask_bits);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, trap_override);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static uint32_t kgd_aldebaran_set_wave_launch_mode(struct amdgpu_device *adev,
|
||||
uint8_t wave_launch_mode,
|
||||
uint32_t vmid)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, LAUNCH_MODE, wave_launch_mode);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#define TCP_WATCH_STRIDE (regTCP_WATCH1_ADDR_H - regTCP_WATCH0_ADDR_H)
|
||||
static uint32_t kgd_gfx_aldebaran_set_address_watch(
|
||||
struct amdgpu_device *adev,
|
||||
uint64_t watch_address,
|
||||
uint32_t watch_address_mask,
|
||||
uint32_t watch_id,
|
||||
uint32_t watch_mode,
|
||||
uint32_t debug_vmid)
|
||||
{
|
||||
uint32_t watch_address_high;
|
||||
uint32_t watch_address_low;
|
||||
uint32_t watch_address_cntl;
|
||||
|
||||
watch_address_cntl = 0;
|
||||
watch_address_low = lower_32_bits(watch_address);
|
||||
watch_address_high = upper_32_bits(watch_address) & 0xffff;
|
||||
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
MODE,
|
||||
watch_mode);
|
||||
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
MASK,
|
||||
watch_address_mask >> 6);
|
||||
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
VALID,
|
||||
1);
|
||||
|
||||
WREG32_RLC((SOC15_REG_OFFSET(GC, 0, regTCP_WATCH0_ADDR_H) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_high);
|
||||
|
||||
WREG32_RLC((SOC15_REG_OFFSET(GC, 0, regTCP_WATCH0_ADDR_L) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_low);
|
||||
|
||||
return watch_address_cntl;
|
||||
}
|
||||
|
||||
static uint32_t kgd_gfx_aldebaran_clear_address_watch(struct amdgpu_device *adev,
|
||||
uint32_t watch_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls aldebaran_kfd2kgd = {
|
||||
.program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
|
||||
@@ -42,5 +185,14 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = {
|
||||
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
|
||||
.set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base,
|
||||
.get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
|
||||
.program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings
|
||||
.enable_debug_trap = kgd_aldebaran_enable_debug_trap,
|
||||
.disable_debug_trap = kgd_aldebaran_disable_debug_trap,
|
||||
.validate_trap_override_request = kgd_aldebaran_validate_trap_override_request,
|
||||
.set_wave_launch_trap_override = kgd_aldebaran_set_wave_launch_trap_override,
|
||||
.set_wave_launch_mode = kgd_aldebaran_set_wave_launch_mode,
|
||||
.set_address_watch = kgd_gfx_aldebaran_set_address_watch,
|
||||
.clear_address_watch = kgd_gfx_aldebaran_clear_address_watch,
|
||||
.get_iq_wait_times = kgd_gfx_v9_get_iq_wait_times,
|
||||
.build_grace_period_packet_info = kgd_gfx_v9_build_grace_period_packet_info,
|
||||
.program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings,
|
||||
};
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_amdkfd_arcturus.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "sdma0/sdma0_4_2_2_offset.h"
|
||||
#include "sdma0/sdma0_4_2_2_sh_mask.h"
|
||||
#include "sdma1/sdma1_4_2_2_offset.h"
|
||||
@@ -48,6 +49,8 @@
|
||||
#include "amdgpu_amdkfd_gfx_v9.h"
|
||||
#include "gfxhub_v1_0.h"
|
||||
#include "mmhub_v9_4.h"
|
||||
#include "gc/gc_9_0_offset.h"
|
||||
#include "gc/gc_9_0_sh_mask.h"
|
||||
|
||||
#define HQD_N_REGS 56
|
||||
#define DUMP_REG(addr) do { \
|
||||
@@ -276,6 +279,117 @@ int kgd_arcturus_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper used to suspend/resume gfx pipe for image post process work to set
|
||||
* barrier behaviour.
|
||||
*/
|
||||
static int suspend_resume_compute_scheduler(struct amdgpu_device *adev, bool suspend)
|
||||
{
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
|
||||
|
||||
if (!(ring && ring->sched.thread))
|
||||
continue;
|
||||
|
||||
/* stop secheduler and drain ring. */
|
||||
if (suspend) {
|
||||
drm_sched_stop(&ring->sched, NULL);
|
||||
r = amdgpu_fence_wait_empty(ring);
|
||||
if (r)
|
||||
goto out;
|
||||
} else {
|
||||
drm_sched_start(&ring->sched, false);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
/* return on resume or failure to drain rings. */
|
||||
if (!suspend || r)
|
||||
return r;
|
||||
|
||||
return amdgpu_device_ip_wait_for_idle(adev, AMD_IP_BLOCK_TYPE_GFX);
|
||||
}
|
||||
|
||||
static void set_barrier_auto_waitcnt(struct amdgpu_device *adev, bool enable_waitcnt)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
WRITE_ONCE(adev->barrier_has_auto_waitcnt, enable_waitcnt);
|
||||
|
||||
if (!down_read_trylock(&adev->reset_domain->sem))
|
||||
return;
|
||||
|
||||
amdgpu_amdkfd_suspend(adev, false);
|
||||
|
||||
if (suspend_resume_compute_scheduler(adev, true))
|
||||
goto out;
|
||||
|
||||
data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CONFIG));
|
||||
data = REG_SET_FIELD(data, SQ_CONFIG, DISABLE_BARRIER_WAITCNT,
|
||||
!enable_waitcnt);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CONFIG), data);
|
||||
|
||||
out:
|
||||
suspend_resume_compute_scheduler(adev, false);
|
||||
|
||||
amdgpu_amdkfd_resume(adev, false);
|
||||
|
||||
up_read(&adev->reset_domain->sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* restore_dbg_registers is ignored here but is a general interface requirement
|
||||
* for devices that support GFXOFF and where the RLC save/restore list
|
||||
* does not support hw registers for debugging i.e. the driver has to manually
|
||||
* initialize the debug mode registers after it has disabled GFX off during the
|
||||
* debug session.
|
||||
*/
|
||||
static uint32_t kgd_arcturus_enable_debug_trap(struct amdgpu_device *adev,
|
||||
bool restore_dbg_registers,
|
||||
uint32_t vmid)
|
||||
{
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
|
||||
|
||||
set_barrier_auto_waitcnt(adev, true);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
|
||||
|
||||
kgd_gfx_v9_set_wave_launch_stall(adev, vmid, false);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* keep_trap_enabled is ignored here but is a general interface requirement
|
||||
* for devices that support multi-process debugging where the performance
|
||||
* overhead from trap temporary setup needs to be bypassed when the debug
|
||||
* session has ended.
|
||||
*/
|
||||
static uint32_t kgd_arcturus_disable_debug_trap(struct amdgpu_device *adev,
|
||||
bool keep_trap_enabled,
|
||||
uint32_t vmid)
|
||||
{
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
|
||||
|
||||
set_barrier_auto_waitcnt(adev, false);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
|
||||
|
||||
kgd_gfx_v9_set_wave_launch_stall(adev, vmid, false);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
const struct kfd2kgd_calls arcturus_kfd2kgd = {
|
||||
.program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
|
||||
.set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping,
|
||||
@@ -294,6 +408,15 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = {
|
||||
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
|
||||
.set_vm_context_page_table_base =
|
||||
kgd_gfx_v9_set_vm_context_page_table_base,
|
||||
.enable_debug_trap = kgd_arcturus_enable_debug_trap,
|
||||
.disable_debug_trap = kgd_arcturus_disable_debug_trap,
|
||||
.validate_trap_override_request = kgd_gfx_v9_validate_trap_override_request,
|
||||
.set_wave_launch_trap_override = kgd_gfx_v9_set_wave_launch_trap_override,
|
||||
.set_wave_launch_mode = kgd_gfx_v9_set_wave_launch_mode,
|
||||
.set_address_watch = kgd_gfx_v9_set_address_watch,
|
||||
.clear_address_watch = kgd_gfx_v9_clear_address_watch,
|
||||
.get_iq_wait_times = kgd_gfx_v9_get_iq_wait_times,
|
||||
.build_grace_period_packet_info = kgd_gfx_v9_build_grace_period_packet_info,
|
||||
.get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
|
||||
.program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings
|
||||
};
|
||||
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_amdkfd_gfx_v9.h"
|
||||
#include "gc/gc_9_4_3_offset.h"
|
||||
#include "gc/gc_9_4_3_sh_mask.h"
|
||||
#include "athub/athub_1_8_0_offset.h"
|
||||
#include "athub/athub_1_8_0_sh_mask.h"
|
||||
#include "oss/osssys_4_4_2_offset.h"
|
||||
#include "oss/osssys_4_4_2_sh_mask.h"
|
||||
#include "v9_structs.h"
|
||||
#include "soc15.h"
|
||||
#include "sdma/sdma_4_4_2_offset.h"
|
||||
#include "sdma/sdma_4_4_2_sh_mask.h"
|
||||
|
||||
static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
{
|
||||
return (struct v9_sdma_mqd *)mqd;
|
||||
}
|
||||
|
||||
static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
|
||||
unsigned int engine_id,
|
||||
unsigned int queue_id)
|
||||
{
|
||||
uint32_t sdma_engine_reg_base =
|
||||
SOC15_REG_OFFSET(SDMA0, GET_INST(SDMA0, engine_id),
|
||||
regSDMA_RLC0_RB_CNTL) -
|
||||
regSDMA_RLC0_RB_CNTL;
|
||||
uint32_t retval = sdma_engine_reg_base +
|
||||
queue_id * (regSDMA_RLC1_RB_CNTL - regSDMA_RLC0_RB_CNTL);
|
||||
|
||||
pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n", engine_id,
|
||||
queue_id, retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int kgd_gfx_v9_4_3_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm)
|
||||
{
|
||||
struct v9_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t data;
|
||||
uint64_t data64;
|
||||
uint64_t __user *wptr64 = (uint64_t __user *)wptr;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
|
||||
m->sdma_queue_id);
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL,
|
||||
m->sdmax_rlcx_rb_cntl & (~SDMA_RLC0_RB_CNTL__RB_ENABLE_MASK));
|
||||
|
||||
end_jiffies = msecs_to_jiffies(2000) + jiffies;
|
||||
while (true) {
|
||||
data = RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_CONTEXT_STATUS);
|
||||
if (data & SDMA_RLC0_CONTEXT_STATUS__IDLE_MASK)
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("SDMA RLC not idle in %s\n", __func__);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_DOORBELL_OFFSET,
|
||||
m->sdmax_rlcx_doorbell_offset);
|
||||
|
||||
data = REG_SET_FIELD(m->sdmax_rlcx_doorbell, SDMA_RLC0_DOORBELL,
|
||||
ENABLE, 1);
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_DOORBELL, data);
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR,
|
||||
m->sdmax_rlcx_rb_rptr);
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR_HI,
|
||||
m->sdmax_rlcx_rb_rptr_hi);
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_MINOR_PTR_UPDATE, 1);
|
||||
if (read_user_wptr(mm, wptr64, data64)) {
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_WPTR,
|
||||
lower_32_bits(data64));
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_WPTR_HI,
|
||||
upper_32_bits(data64));
|
||||
} else {
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_WPTR,
|
||||
m->sdmax_rlcx_rb_rptr);
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_WPTR_HI,
|
||||
m->sdmax_rlcx_rb_rptr_hi);
|
||||
}
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_MINOR_PTR_UPDATE, 0);
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_BASE_HI,
|
||||
m->sdmax_rlcx_rb_base_hi);
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR_ADDR_LO,
|
||||
m->sdmax_rlcx_rb_rptr_addr_lo);
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR_ADDR_HI,
|
||||
m->sdmax_rlcx_rb_rptr_addr_hi);
|
||||
|
||||
data = REG_SET_FIELD(m->sdmax_rlcx_rb_cntl, SDMA_RLC0_RB_CNTL,
|
||||
RB_ENABLE, 1);
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_gfx_v9_4_3_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||
engine_id, queue_id);
|
||||
uint32_t i = 0, reg;
|
||||
#undef HQD_N_REGS
|
||||
#define HQD_N_REGS (19+6+7+12)
|
||||
#define DUMP_REG(addr) do { \
|
||||
if (WARN_ON_ONCE(i >= HQD_N_REGS)) \
|
||||
break; \
|
||||
(*dump)[i][0] = (addr) << 2; \
|
||||
(*dump)[i++][1] = RREG32(addr); \
|
||||
} while (0)
|
||||
|
||||
*dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (reg = regSDMA_RLC0_RB_CNTL; reg <= regSDMA_RLC0_DOORBELL; reg++)
|
||||
DUMP_REG(sdma_rlc_reg_offset + reg);
|
||||
for (reg = regSDMA_RLC0_STATUS; reg <= regSDMA_RLC0_CSA_ADDR_HI; reg++)
|
||||
DUMP_REG(sdma_rlc_reg_offset + reg);
|
||||
for (reg = regSDMA_RLC0_IB_SUB_REMAIN;
|
||||
reg <= regSDMA_RLC0_MINOR_PTR_UPDATE; reg++)
|
||||
DUMP_REG(sdma_rlc_reg_offset + reg);
|
||||
for (reg = regSDMA_RLC0_MIDCMD_DATA0;
|
||||
reg <= regSDMA_RLC0_MIDCMD_CNTL; reg++)
|
||||
DUMP_REG(sdma_rlc_reg_offset + reg);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool kgd_gfx_v9_4_3_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||
{
|
||||
struct v9_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t sdma_rlc_rb_cntl;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
|
||||
m->sdma_queue_id);
|
||||
|
||||
sdma_rlc_rb_cntl = RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL);
|
||||
|
||||
if (sdma_rlc_rb_cntl & SDMA_RLC0_RB_CNTL__RB_ENABLE_MASK)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int kgd_gfx_v9_4_3_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
struct v9_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t temp;
|
||||
unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
|
||||
m->sdma_queue_id);
|
||||
|
||||
temp = RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL);
|
||||
temp = temp & ~SDMA_RLC0_RB_CNTL__RB_ENABLE_MASK;
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL, temp);
|
||||
|
||||
while (true) {
|
||||
temp = RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_CONTEXT_STATUS);
|
||||
if (temp & SDMA_RLC0_CONTEXT_STATUS__IDLE_MASK)
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("SDMA RLC not idle in %s\n", __func__);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_DOORBELL, 0);
|
||||
WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL,
|
||||
RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL) |
|
||||
SDMA_RLC0_RB_CNTL__RB_ENABLE_MASK);
|
||||
|
||||
m->sdmax_rlcx_rb_rptr =
|
||||
RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR);
|
||||
m->sdmax_rlcx_rb_rptr_hi =
|
||||
RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR_HI);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_gfx_v9_4_3_set_pasid_vmid_mapping(struct amdgpu_device *adev,
|
||||
u32 pasid, unsigned int vmid, uint32_t xcc_inst)
|
||||
{
|
||||
unsigned long timeout;
|
||||
unsigned int reg;
|
||||
unsigned int phy_inst = GET_INST(GC, xcc_inst);
|
||||
/* Every two XCCs share one AID */
|
||||
unsigned int aid = phy_inst / 2;
|
||||
|
||||
/*
|
||||
* We have to assume that there is no outstanding mapping.
|
||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||
* a mapping is in progress or because a mapping finished
|
||||
* and the SW cleared it.
|
||||
* So the protocol is to always wait & clear.
|
||||
*/
|
||||
uint32_t pasid_mapping = (pasid == 0) ? 0 : (uint32_t)pasid |
|
||||
ATC_VMID0_PASID_MAPPING__VALID_MASK;
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(ATHUB, 0,
|
||||
regATC_VMID0_PASID_MAPPING) + vmid, pasid_mapping);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(10);
|
||||
while (!(RREG32(SOC15_REG_OFFSET(ATHUB, 0,
|
||||
regATC_VMID_PASID_MAPPING_UPDATE_STATUS)) &
|
||||
(1U << vmid))) {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
pr_err("Fail to program VMID-PASID mapping\n");
|
||||
return -ETIME;
|
||||
}
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(ATHUB, 0,
|
||||
regATC_VMID_PASID_MAPPING_UPDATE_STATUS),
|
||||
1U << vmid);
|
||||
|
||||
reg = RREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_LUT_INDEX));
|
||||
/* Every 4 numbers is a cycle. 1st is AID, 2nd and 3rd are XCDs,
|
||||
* and the 4th is reserved. Therefore "aid * 4 + (xcc_inst % 2) + 1"
|
||||
* programs _LUT for XCC and "aid * 4" for AID where the XCC connects
|
||||
* to.
|
||||
*/
|
||||
WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_LUT_INDEX),
|
||||
aid * 4 + (phy_inst % 2) + 1);
|
||||
WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_0_LUT) + vmid,
|
||||
pasid_mapping);
|
||||
WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_LUT_INDEX),
|
||||
aid * 4);
|
||||
WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_0_LUT_MM) + vmid,
|
||||
pasid_mapping);
|
||||
WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_LUT_INDEX), reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct v9_mqd *get_mqd(void *mqd)
|
||||
{
|
||||
return (struct v9_mqd *)mqd;
|
||||
}
|
||||
|
||||
static int kgd_gfx_v9_4_3_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
|
||||
{
|
||||
struct v9_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
uint32_t reg, hqd_base, hqd_end, data;
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
|
||||
|
||||
/* HQD registers extend to CP_HQD_AQL_DISPATCH_ID_HI */
|
||||
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
||||
hqd_base = SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_MQD_BASE_ADDR);
|
||||
hqd_end = SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_AQL_DISPATCH_ID_HI);
|
||||
|
||||
for (reg = hqd_base; reg <= hqd_end; reg++)
|
||||
WREG32_RLC(reg, mqd_hqd[reg - hqd_base]);
|
||||
|
||||
|
||||
/* Activate doorbell logic before triggering WPTR poll. */
|
||||
data = REG_SET_FIELD(m->cp_hqd_pq_doorbell_control,
|
||||
CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_DOORBELL_CONTROL),
|
||||
data);
|
||||
|
||||
if (wptr) {
|
||||
/* Don't read wptr with get_user because the user
|
||||
* context may not be accessible (if this function
|
||||
* runs in a work queue). Instead trigger a one-shot
|
||||
* polling read from memory in the CP. This assumes
|
||||
* that wptr is GPU-accessible in the queue's VMID via
|
||||
* ATC or SVM. WPTR==RPTR before starting the poll so
|
||||
* the CP starts fetching new commands from the right
|
||||
* place.
|
||||
*
|
||||
* Guessing a 64-bit WPTR from a 32-bit RPTR is a bit
|
||||
* tricky. Assume that the queue didn't overflow. The
|
||||
* number of valid bits in the 32-bit RPTR depends on
|
||||
* the queue size. The remaining bits are taken from
|
||||
* the saved 64-bit WPTR. If the WPTR wrapped, add the
|
||||
* queue size.
|
||||
*/
|
||||
uint32_t queue_size =
|
||||
2 << REG_GET_FIELD(m->cp_hqd_pq_control,
|
||||
CP_HQD_PQ_CONTROL, QUEUE_SIZE);
|
||||
uint64_t guessed_wptr = m->cp_hqd_pq_rptr & (queue_size - 1);
|
||||
|
||||
if ((m->cp_hqd_pq_wptr_lo & (queue_size - 1)) < guessed_wptr)
|
||||
guessed_wptr += queue_size;
|
||||
guessed_wptr += m->cp_hqd_pq_wptr_lo & ~(queue_size - 1);
|
||||
guessed_wptr += (uint64_t)m->cp_hqd_pq_wptr_hi << 32;
|
||||
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_LO),
|
||||
lower_32_bits(guessed_wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_HI),
|
||||
upper_32_bits(guessed_wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_POLL_ADDR),
|
||||
lower_32_bits((uintptr_t)wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
|
||||
regCP_HQD_PQ_WPTR_POLL_ADDR_HI),
|
||||
upper_32_bits((uintptr_t)wptr));
|
||||
WREG32(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_PQ_WPTR_POLL_CNTL1),
|
||||
(uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id,
|
||||
queue_id));
|
||||
}
|
||||
|
||||
/* Start the EOP fetcher */
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_EOP_RPTR),
|
||||
REG_SET_FIELD(m->cp_hqd_eop_rptr,
|
||||
CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
|
||||
|
||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_ACTIVE), data);
|
||||
|
||||
kgd_gfx_v9_release_queue(adev, inst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls gc_9_4_3_kfd2kgd = {
|
||||
.program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
|
||||
.set_pasid_vmid_mapping = kgd_gfx_v9_4_3_set_pasid_vmid_mapping,
|
||||
.init_interrupts = kgd_gfx_v9_init_interrupts,
|
||||
.hqd_load = kgd_gfx_v9_4_3_hqd_load,
|
||||
.hiq_mqd_load = kgd_gfx_v9_hiq_mqd_load,
|
||||
.hqd_sdma_load = kgd_gfx_v9_4_3_hqd_sdma_load,
|
||||
.hqd_dump = kgd_gfx_v9_hqd_dump,
|
||||
.hqd_sdma_dump = kgd_gfx_v9_4_3_hqd_sdma_dump,
|
||||
.hqd_is_occupied = kgd_gfx_v9_hqd_is_occupied,
|
||||
.hqd_sdma_is_occupied = kgd_gfx_v9_4_3_hqd_sdma_is_occupied,
|
||||
.hqd_destroy = kgd_gfx_v9_hqd_destroy,
|
||||
.hqd_sdma_destroy = kgd_gfx_v9_4_3_hqd_sdma_destroy,
|
||||
.wave_control_execute = kgd_gfx_v9_wave_control_execute,
|
||||
.get_atc_vmid_pasid_mapping_info =
|
||||
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
|
||||
.set_vm_context_page_table_base =
|
||||
kgd_gfx_v9_set_vm_context_page_table_base,
|
||||
.program_trap_handler_settings =
|
||||
kgd_gfx_v9_program_trap_handler_settings
|
||||
};
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_amdkfd_gfx_v10.h"
|
||||
#include "gc/gc_10_1_0_offset.h"
|
||||
#include "gc/gc_10_1_0_sh_mask.h"
|
||||
#include "athub/athub_2_0_0_offset.h"
|
||||
@@ -31,6 +32,7 @@
|
||||
#include "v10_structs.h"
|
||||
#include "nv.h"
|
||||
#include "nvd.h"
|
||||
#include <uapi/linux/kfd_ioctl.h>
|
||||
|
||||
enum hqd_dequeue_request_type {
|
||||
NO_ACTION = 0,
|
||||
@@ -79,7 +81,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
uint32_t sh_mem_bases, uint32_t inst)
|
||||
{
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
@@ -91,7 +93,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
unsigned int vmid)
|
||||
unsigned int vmid, uint32_t inst)
|
||||
{
|
||||
/*
|
||||
* We have to assume that there is no outstanding mapping.
|
||||
@@ -135,7 +137,8 @@ static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
* but still works
|
||||
*/
|
||||
|
||||
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t inst)
|
||||
{
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
@@ -205,7 +208,7 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm)
|
||||
uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
|
||||
{
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
@@ -286,9 +289,9 @@ static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
|
||||
static int kgd_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t doorbell_off)
|
||||
uint32_t doorbell_off, uint32_t inst)
|
||||
{
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t mec, pipe;
|
||||
int r;
|
||||
@@ -303,7 +306,7 @@ static int kgd_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
|
||||
mec, pipe, queue_id);
|
||||
|
||||
spin_lock(&adev->gfx.kiq.ring_lock);
|
||||
spin_lock(&adev->gfx.kiq[0].ring_lock);
|
||||
r = amdgpu_ring_alloc(kiq_ring, 7);
|
||||
if (r) {
|
||||
pr_err("Failed to alloc KIQ (%d).\n", r);
|
||||
@@ -330,7 +333,7 @@ static int kgd_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
spin_unlock(&adev->gfx.kiq[0].ring_lock);
|
||||
release_queue(adev);
|
||||
|
||||
return r;
|
||||
@@ -338,7 +341,7 @@ out_unlock:
|
||||
|
||||
static int kgd_hqd_dump(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
|
||||
{
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS 56
|
||||
@@ -469,7 +472,7 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
|
||||
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
@@ -510,7 +513,7 @@ static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long end_jiffies;
|
||||
@@ -673,7 +676,7 @@ static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
|
||||
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
uint32_t sq_cmd, uint32_t inst)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
@@ -708,8 +711,295 @@ static void set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
|
||||
}
|
||||
|
||||
/*
|
||||
* GFX10 helper for wave launch stall requirements on debug trap setting.
|
||||
*
|
||||
* vmid:
|
||||
* Target VMID to stall/unstall.
|
||||
*
|
||||
* stall:
|
||||
* 0-unstall wave launch (enable), 1-stall wave launch (disable).
|
||||
* After wavefront launch has been stalled, allocated waves must drain from
|
||||
* SPI in order for debug trap settings to take effect on those waves.
|
||||
* This is roughly a ~3500 clock cycle wait on SPI where a read on
|
||||
* SPI_GDBG_WAVE_CNTL translates to ~32 clock cycles.
|
||||
* KGD_GFX_V10_WAVE_LAUNCH_SPI_DRAIN_LATENCY indicates the number of reads required.
|
||||
*
|
||||
* NOTE: We can afford to clear the entire STALL_VMID field on unstall
|
||||
* because current GFX10 chips cannot support multi-process debugging due to
|
||||
* trap configuration and masking being limited to global scope. Always
|
||||
* assume single process conditions.
|
||||
*
|
||||
*/
|
||||
|
||||
#define KGD_GFX_V10_WAVE_LAUNCH_SPI_DRAIN_LATENCY 110
|
||||
static void kgd_gfx_v10_set_wave_launch_stall(struct amdgpu_device *adev, uint32_t vmid, bool stall)
|
||||
{
|
||||
uint32_t data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
|
||||
int i;
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_VMID,
|
||||
stall ? 1 << vmid : 0);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
|
||||
|
||||
if (!stall)
|
||||
return;
|
||||
|
||||
for (i = 0; i < KGD_GFX_V10_WAVE_LAUNCH_SPI_DRAIN_LATENCY; i++)
|
||||
RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
|
||||
}
|
||||
|
||||
uint32_t kgd_gfx_v10_enable_debug_trap(struct amdgpu_device *adev,
|
||||
bool restore_dbg_registers,
|
||||
uint32_t vmid)
|
||||
{
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
kgd_gfx_v10_set_wave_launch_stall(adev, vmid, true);
|
||||
|
||||
/* assume gfx off is disabled for the debug session if rlc restore not supported. */
|
||||
if (restore_dbg_registers) {
|
||||
uint32_t data = 0;
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_TRAP_CONFIG,
|
||||
VMID_SEL, 1 << vmid);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_TRAP_CONFIG,
|
||||
TRAP_EN, 1);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_CONFIG), data);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_DATA0), 0);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_DATA1), 0);
|
||||
|
||||
kgd_gfx_v10_set_wave_launch_stall(adev, vmid, false);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
|
||||
|
||||
kgd_gfx_v10_set_wave_launch_stall(adev, vmid, false);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t kgd_gfx_v10_disable_debug_trap(struct amdgpu_device *adev,
|
||||
bool keep_trap_enabled,
|
||||
uint32_t vmid)
|
||||
{
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
kgd_gfx_v10_set_wave_launch_stall(adev, vmid, true);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
|
||||
|
||||
kgd_gfx_v10_set_wave_launch_stall(adev, vmid, false);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kgd_gfx_v10_validate_trap_override_request(struct amdgpu_device *adev,
|
||||
uint32_t trap_override,
|
||||
uint32_t *trap_mask_supported)
|
||||
{
|
||||
*trap_mask_supported &= KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH;
|
||||
|
||||
/* The SPI_GDBG_TRAP_MASK register is global and affects all
|
||||
* processes. Only allow OR-ing the address-watch bit, since
|
||||
* this only affects processes under the debugger. Other bits
|
||||
* should stay 0 to avoid the debugger interfering with other
|
||||
* processes.
|
||||
*/
|
||||
if (trap_override != KFD_DBG_TRAP_OVERRIDE_OR)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t kgd_gfx_v10_set_wave_launch_trap_override(struct amdgpu_device *adev,
|
||||
uint32_t vmid,
|
||||
uint32_t trap_override,
|
||||
uint32_t trap_mask_bits,
|
||||
uint32_t trap_mask_request,
|
||||
uint32_t *trap_mask_prev,
|
||||
uint32_t kfd_dbg_trap_cntl_prev)
|
||||
{
|
||||
uint32_t data, wave_cntl_prev;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
wave_cntl_prev = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
|
||||
|
||||
kgd_gfx_v10_set_wave_launch_stall(adev, vmid, true);
|
||||
|
||||
data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK));
|
||||
*trap_mask_prev = REG_GET_FIELD(data, SPI_GDBG_TRAP_MASK, EXCP_EN);
|
||||
|
||||
trap_mask_bits = (trap_mask_bits & trap_mask_request) |
|
||||
(*trap_mask_prev & ~trap_mask_request);
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK, EXCP_EN, trap_mask_bits);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK, REPLACE, trap_override);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), data);
|
||||
|
||||
/* We need to preserve wave launch mode stall settings. */
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), wave_cntl_prev);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t kgd_gfx_v10_set_wave_launch_mode(struct amdgpu_device *adev,
|
||||
uint8_t wave_launch_mode,
|
||||
uint32_t vmid)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
bool is_mode_set = !!wave_launch_mode;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
kgd_gfx_v10_set_wave_launch_stall(adev, vmid, true);
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
|
||||
VMID_MASK, is_mode_set ? 1 << vmid : 0);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
|
||||
MODE, is_mode_set ? wave_launch_mode : 0);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL2), data);
|
||||
|
||||
kgd_gfx_v10_set_wave_launch_stall(adev, vmid, false);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TCP_WATCH_STRIDE (mmTCP_WATCH1_ADDR_H - mmTCP_WATCH0_ADDR_H)
|
||||
uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev,
|
||||
uint64_t watch_address,
|
||||
uint32_t watch_address_mask,
|
||||
uint32_t watch_id,
|
||||
uint32_t watch_mode,
|
||||
uint32_t debug_vmid)
|
||||
{
|
||||
uint32_t watch_address_high;
|
||||
uint32_t watch_address_low;
|
||||
uint32_t watch_address_cntl;
|
||||
|
||||
watch_address_cntl = 0;
|
||||
|
||||
watch_address_low = lower_32_bits(watch_address);
|
||||
watch_address_high = upper_32_bits(watch_address) & 0xffff;
|
||||
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
VMID,
|
||||
debug_vmid);
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
MODE,
|
||||
watch_mode);
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
MASK,
|
||||
watch_address_mask >> 7);
|
||||
|
||||
/* Turning off this watch point until we set all the registers */
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
VALID,
|
||||
0);
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_cntl);
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_H) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_high);
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_L) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_low);
|
||||
|
||||
/* Enable the watch point */
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
VALID,
|
||||
1);
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_cntl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t kgd_gfx_v10_clear_address_watch(struct amdgpu_device *adev,
|
||||
uint32_t watch_id)
|
||||
{
|
||||
uint32_t watch_address_cntl;
|
||||
|
||||
watch_address_cntl = 0;
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_cntl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* kgd_gfx_v10_get_iq_wait_times: Returns the mmCP_IQ_WAIT_TIME1/2 values
|
||||
* The values read are:
|
||||
* ib_offload_wait_time -- Wait Count for Indirect Buffer Offloads.
|
||||
* atomic_offload_wait_time -- Wait Count for L2 and GDS Atomics Offloads.
|
||||
* wrm_offload_wait_time -- Wait Count for WAIT_REG_MEM Offloads.
|
||||
* gws_wait_time -- Wait Count for Global Wave Syncs.
|
||||
* que_sleep_wait_time -- Wait Count for Dequeue Retry.
|
||||
* sch_wave_wait_time -- Wait Count for Scheduling Wave Message.
|
||||
* sem_rearm_wait_time -- Wait Count for Semaphore re-arm.
|
||||
* deq_retry_wait_time -- Wait Count for Global Wave Syncs.
|
||||
*/
|
||||
void kgd_gfx_v10_get_iq_wait_times(struct amdgpu_device *adev,
|
||||
uint32_t *wait_times)
|
||||
|
||||
{
|
||||
*wait_times = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2));
|
||||
}
|
||||
|
||||
void kgd_gfx_v10_build_grace_period_packet_info(struct amdgpu_device *adev,
|
||||
uint32_t wait_times,
|
||||
uint32_t grace_period,
|
||||
uint32_t *reg_offset,
|
||||
uint32_t *reg_data)
|
||||
{
|
||||
*reg_data = wait_times;
|
||||
|
||||
/*
|
||||
* The CP cannont handle a 0 grace period input and will result in
|
||||
* an infinite grace period being set so set to 1 to prevent this.
|
||||
*/
|
||||
if (grace_period == 0)
|
||||
grace_period = 1;
|
||||
|
||||
*reg_data = REG_SET_FIELD(*reg_data,
|
||||
CP_IQ_WAIT_TIME2,
|
||||
SCH_WAVE,
|
||||
grace_period);
|
||||
|
||||
*reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2);
|
||||
}
|
||||
|
||||
static void program_trap_handler_settings(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr,
|
||||
uint32_t inst)
|
||||
{
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
@@ -750,5 +1040,14 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
|
||||
.get_atc_vmid_pasid_mapping_info =
|
||||
get_atc_vmid_pasid_mapping_info,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base,
|
||||
.enable_debug_trap = kgd_gfx_v10_enable_debug_trap,
|
||||
.disable_debug_trap = kgd_gfx_v10_disable_debug_trap,
|
||||
.validate_trap_override_request = kgd_gfx_v10_validate_trap_override_request,
|
||||
.set_wave_launch_trap_override = kgd_gfx_v10_set_wave_launch_trap_override,
|
||||
.set_wave_launch_mode = kgd_gfx_v10_set_wave_launch_mode,
|
||||
.set_address_watch = kgd_gfx_v10_set_address_watch,
|
||||
.clear_address_watch = kgd_gfx_v10_clear_address_watch,
|
||||
.get_iq_wait_times = kgd_gfx_v10_get_iq_wait_times,
|
||||
.build_grace_period_packet_info = kgd_gfx_v10_build_grace_period_packet_info,
|
||||
.program_trap_handler_settings = program_trap_handler_settings,
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2023 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
uint32_t kgd_gfx_v10_enable_debug_trap(struct amdgpu_device *adev,
|
||||
bool restore_dbg_registers,
|
||||
uint32_t vmid);
|
||||
uint32_t kgd_gfx_v10_disable_debug_trap(struct amdgpu_device *adev,
|
||||
bool keep_trap_enabled,
|
||||
uint32_t vmid);
|
||||
int kgd_gfx_v10_validate_trap_override_request(struct amdgpu_device *adev,
|
||||
uint32_t trap_override,
|
||||
uint32_t *trap_mask_supported);
|
||||
uint32_t kgd_gfx_v10_set_wave_launch_trap_override(struct amdgpu_device *adev,
|
||||
uint32_t vmid,
|
||||
uint32_t trap_override,
|
||||
uint32_t trap_mask_bits,
|
||||
uint32_t trap_mask_request,
|
||||
uint32_t *trap_mask_prev,
|
||||
uint32_t kfd_dbg_trap_cntl_prev);
|
||||
uint32_t kgd_gfx_v10_set_wave_launch_mode(struct amdgpu_device *adev,
|
||||
uint8_t wave_launch_mode,
|
||||
uint32_t vmid);
|
||||
uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev,
|
||||
uint64_t watch_address,
|
||||
uint32_t watch_address_mask,
|
||||
uint32_t watch_id,
|
||||
uint32_t watch_mode,
|
||||
uint32_t debug_vmid);
|
||||
uint32_t kgd_gfx_v10_clear_address_watch(struct amdgpu_device *adev,
|
||||
uint32_t watch_id);
|
||||
void kgd_gfx_v10_get_iq_wait_times(struct amdgpu_device *adev, uint32_t *wait_times);
|
||||
void kgd_gfx_v10_build_grace_period_packet_info(struct amdgpu_device *adev,
|
||||
uint32_t wait_times,
|
||||
uint32_t grace_period,
|
||||
uint32_t *reg_offset,
|
||||
uint32_t *reg_data);
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/mmu_context.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_amdkfd_gfx_v10.h"
|
||||
#include "gc/gc_10_3_0_offset.h"
|
||||
#include "gc/gc_10_3_0_sh_mask.h"
|
||||
#include "oss/osssys_5_0_0_offset.h"
|
||||
@@ -80,7 +81,7 @@ static void program_sh_mem_settings_v10_3(struct amdgpu_device *adev, uint32_t v
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
uint32_t sh_mem_bases, uint32_t inst)
|
||||
{
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
@@ -93,7 +94,7 @@ static void program_sh_mem_settings_v10_3(struct amdgpu_device *adev, uint32_t v
|
||||
|
||||
/* ATC is defeatured on Sienna_Cichlid */
|
||||
static int set_pasid_vmid_mapping_v10_3(struct amdgpu_device *adev, unsigned int pasid,
|
||||
unsigned int vmid)
|
||||
unsigned int vmid, uint32_t inst)
|
||||
{
|
||||
uint32_t value = pasid << IH_VMID_0_LUT__PASID__SHIFT;
|
||||
|
||||
@@ -105,7 +106,8 @@ static int set_pasid_vmid_mapping_v10_3(struct amdgpu_device *adev, unsigned int
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_interrupts_v10_3(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
static int init_interrupts_v10_3(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t inst)
|
||||
{
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
@@ -177,7 +179,7 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
static int hqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm)
|
||||
uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
|
||||
{
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
@@ -273,9 +275,9 @@ static int hqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
|
||||
static int hiq_mqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t doorbell_off)
|
||||
uint32_t doorbell_off, uint32_t inst)
|
||||
{
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t mec, pipe;
|
||||
int r;
|
||||
@@ -290,7 +292,7 @@ static int hiq_mqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
|
||||
mec, pipe, queue_id);
|
||||
|
||||
spin_lock(&adev->gfx.kiq.ring_lock);
|
||||
spin_lock(&adev->gfx.kiq[0].ring_lock);
|
||||
r = amdgpu_ring_alloc(kiq_ring, 7);
|
||||
if (r) {
|
||||
pr_err("Failed to alloc KIQ (%d).\n", r);
|
||||
@@ -317,7 +319,7 @@ static int hiq_mqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
spin_unlock(&adev->gfx.kiq[0].ring_lock);
|
||||
release_queue(adev);
|
||||
|
||||
return r;
|
||||
@@ -325,7 +327,7 @@ out_unlock:
|
||||
|
||||
static int hqd_dump_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
|
||||
{
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS 56
|
||||
@@ -456,7 +458,7 @@ static int hqd_sdma_dump_v10_3(struct amdgpu_device *adev,
|
||||
|
||||
static bool hqd_is_occupied_v10_3(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
@@ -498,7 +500,7 @@ static bool hqd_sdma_is_occupied_v10_3(struct amdgpu_device *adev,
|
||||
static int hqd_destroy_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long end_jiffies;
|
||||
@@ -586,7 +588,7 @@ static int hqd_sdma_destroy_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
|
||||
static int wave_control_execute_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
uint32_t sq_cmd, uint32_t inst)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
@@ -628,7 +630,8 @@ static void set_vm_context_page_table_base_v10_3(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
static void program_trap_handler_settings_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr,
|
||||
uint32_t inst)
|
||||
{
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
@@ -652,142 +655,6 @@ static void program_trap_handler_settings_v10_3(struct amdgpu_device *adev,
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint32_t enable_debug_trap_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t trap_debug_wave_launch_mode,
|
||||
uint32_t vmid)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
uint32_t orig_wave_cntl_value;
|
||||
uint32_t orig_stall_vmid;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
orig_wave_cntl_value = RREG32(SOC15_REG_OFFSET(GC,
|
||||
0,
|
||||
mmSPI_GDBG_WAVE_CNTL));
|
||||
orig_stall_vmid = REG_GET_FIELD(orig_wave_cntl_value,
|
||||
SPI_GDBG_WAVE_CNTL,
|
||||
STALL_VMID);
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA, 1);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
|
||||
|
||||
data = 0;
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), data);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), orig_stall_vmid);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t disable_debug_trap_v10_3(struct amdgpu_device *adev)
|
||||
{
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t set_wave_launch_trap_override_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t trap_override,
|
||||
uint32_t trap_mask)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA, 1);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
|
||||
|
||||
data = 0;
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK,
|
||||
EXCP_EN, trap_mask);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK,
|
||||
REPLACE, trap_override);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), data);
|
||||
|
||||
data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA, 0);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t set_wave_launch_mode_v10_3(struct amdgpu_device *adev,
|
||||
uint8_t wave_launch_mode,
|
||||
uint32_t vmid)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
bool is_stall_mode;
|
||||
bool is_mode_set;
|
||||
|
||||
is_stall_mode = (wave_launch_mode == 4);
|
||||
is_mode_set = (wave_launch_mode != 0 && wave_launch_mode != 4);
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
|
||||
VMID_MASK, is_mode_set ? 1 << vmid : 0);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
|
||||
MODE, is_mode_set ? wave_launch_mode : 0);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL2), data);
|
||||
|
||||
data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL,
|
||||
STALL_VMID, is_stall_mode ? 1 << vmid : 0);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL,
|
||||
STALL_RA, is_stall_mode ? 1 : 0);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* kgd_get_iq_wait_times: Returns the mmCP_IQ_WAIT_TIME1/2 values
|
||||
* The values read are:
|
||||
* ib_offload_wait_time -- Wait Count for Indirect Buffer Offloads.
|
||||
* atomic_offload_wait_time -- Wait Count for L2 and GDS Atomics Offloads.
|
||||
* wrm_offload_wait_time -- Wait Count for WAIT_REG_MEM Offloads.
|
||||
* gws_wait_time -- Wait Count for Global Wave Syncs.
|
||||
* que_sleep_wait_time -- Wait Count for Dequeue Retry.
|
||||
* sch_wave_wait_time -- Wait Count for Scheduling Wave Message.
|
||||
* sem_rearm_wait_time -- Wait Count for Semaphore re-arm.
|
||||
* deq_retry_wait_time -- Wait Count for Global Wave Syncs.
|
||||
*/
|
||||
void get_iq_wait_times_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t *wait_times)
|
||||
|
||||
{
|
||||
*wait_times = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2));
|
||||
}
|
||||
|
||||
void build_grace_period_packet_info_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t wait_times,
|
||||
uint32_t grace_period,
|
||||
uint32_t *reg_offset,
|
||||
uint32_t *reg_data)
|
||||
{
|
||||
*reg_data = wait_times;
|
||||
|
||||
*reg_data = REG_SET_FIELD(*reg_data,
|
||||
CP_IQ_WAIT_TIME2,
|
||||
SCH_WAVE,
|
||||
grace_period);
|
||||
|
||||
*reg_offset = mmCP_IQ_WAIT_TIME2;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = {
|
||||
.program_sh_mem_settings = program_sh_mem_settings_v10_3,
|
||||
.set_pasid_vmid_mapping = set_pasid_vmid_mapping_v10_3,
|
||||
@@ -805,12 +672,13 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = {
|
||||
.get_atc_vmid_pasid_mapping_info = get_atc_vmid_pasid_mapping_info_v10_3,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3,
|
||||
.program_trap_handler_settings = program_trap_handler_settings_v10_3,
|
||||
#if 0
|
||||
.enable_debug_trap = enable_debug_trap_v10_3,
|
||||
.disable_debug_trap = disable_debug_trap_v10_3,
|
||||
.set_wave_launch_trap_override = set_wave_launch_trap_override_v10_3,
|
||||
.set_wave_launch_mode = set_wave_launch_mode_v10_3,
|
||||
.get_iq_wait_times = get_iq_wait_times_v10_3,
|
||||
.build_grace_period_packet_info = build_grace_period_packet_info_v10_3,
|
||||
#endif
|
||||
.get_iq_wait_times = kgd_gfx_v10_get_iq_wait_times,
|
||||
.build_grace_period_packet_info = kgd_gfx_v10_build_grace_period_packet_info,
|
||||
.enable_debug_trap = kgd_gfx_v10_enable_debug_trap,
|
||||
.disable_debug_trap = kgd_gfx_v10_disable_debug_trap,
|
||||
.validate_trap_override_request = kgd_gfx_v10_validate_trap_override_request,
|
||||
.set_wave_launch_trap_override = kgd_gfx_v10_set_wave_launch_trap_override,
|
||||
.set_wave_launch_mode = kgd_gfx_v10_set_wave_launch_mode,
|
||||
.set_address_watch = kgd_gfx_v10_set_address_watch,
|
||||
.clear_address_watch = kgd_gfx_v10_clear_address_watch
|
||||
};
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "soc15d.h"
|
||||
#include "v11_structs.h"
|
||||
#include "soc21.h"
|
||||
#include <uapi/linux/kfd_ioctl.h>
|
||||
|
||||
enum hqd_dequeue_request_type {
|
||||
NO_ACTION = 0,
|
||||
@@ -78,7 +79,7 @@ static void program_sh_mem_settings_v11(struct amdgpu_device *adev, uint32_t vmi
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
uint32_t sh_mem_bases, uint32_t inst)
|
||||
{
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
@@ -89,7 +90,7 @@ static void program_sh_mem_settings_v11(struct amdgpu_device *adev, uint32_t vmi
|
||||
}
|
||||
|
||||
static int set_pasid_vmid_mapping_v11(struct amdgpu_device *adev, unsigned int pasid,
|
||||
unsigned int vmid)
|
||||
unsigned int vmid, uint32_t inst)
|
||||
{
|
||||
uint32_t value = pasid << IH_VMID_0_LUT__PASID__SHIFT;
|
||||
|
||||
@@ -101,7 +102,8 @@ static int set_pasid_vmid_mapping_v11(struct amdgpu_device *adev, unsigned int p
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_interrupts_v11(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
static int init_interrupts_v11(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t inst)
|
||||
{
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
@@ -162,7 +164,7 @@ static inline struct v11_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
static int hqd_load_v11(struct amdgpu_device *adev, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm)
|
||||
struct mm_struct *mm, uint32_t inst)
|
||||
{
|
||||
struct v11_compute_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
@@ -258,9 +260,9 @@ static int hqd_load_v11(struct amdgpu_device *adev, void *mqd, uint32_t pipe_id,
|
||||
|
||||
static int hiq_mqd_load_v11(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t doorbell_off)
|
||||
uint32_t doorbell_off, uint32_t inst)
|
||||
{
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
|
||||
struct v11_compute_mqd *m;
|
||||
uint32_t mec, pipe;
|
||||
int r;
|
||||
@@ -275,7 +277,7 @@ static int hiq_mqd_load_v11(struct amdgpu_device *adev, void *mqd,
|
||||
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
|
||||
mec, pipe, queue_id);
|
||||
|
||||
spin_lock(&adev->gfx.kiq.ring_lock);
|
||||
spin_lock(&adev->gfx.kiq[0].ring_lock);
|
||||
r = amdgpu_ring_alloc(kiq_ring, 7);
|
||||
if (r) {
|
||||
pr_err("Failed to alloc KIQ (%d).\n", r);
|
||||
@@ -302,7 +304,7 @@ static int hiq_mqd_load_v11(struct amdgpu_device *adev, void *mqd,
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
spin_unlock(&adev->gfx.kiq[0].ring_lock);
|
||||
release_queue(adev);
|
||||
|
||||
return r;
|
||||
@@ -310,7 +312,7 @@ out_unlock:
|
||||
|
||||
static int hqd_dump_v11(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
|
||||
{
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS 56
|
||||
@@ -445,7 +447,7 @@ static int hqd_sdma_dump_v11(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
static bool hqd_is_occupied_v11(struct amdgpu_device *adev, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
uint32_t pipe_id, uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
@@ -486,7 +488,7 @@ static bool hqd_sdma_is_occupied_v11(struct amdgpu_device *adev, void *mqd)
|
||||
static int hqd_destroy_v11(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long end_jiffies;
|
||||
@@ -571,7 +573,7 @@ static int hqd_sdma_destroy_v11(struct amdgpu_device *adev, void *mqd,
|
||||
|
||||
static int wave_control_execute_v11(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
uint32_t sq_cmd, uint32_t inst)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
@@ -606,6 +608,183 @@ static void set_vm_context_page_table_base_v11(struct amdgpu_device *adev,
|
||||
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns TRAP_EN, EXCP_EN and EXCP_REPLACE.
|
||||
*
|
||||
* restore_dbg_registers is ignored here but is a general interface requirement
|
||||
* for devices that support GFXOFF and where the RLC save/restore list
|
||||
* does not support hw registers for debugging i.e. the driver has to manually
|
||||
* initialize the debug mode registers after it has disabled GFX off during the
|
||||
* debug session.
|
||||
*/
|
||||
static uint32_t kgd_gfx_v11_enable_debug_trap(struct amdgpu_device *adev,
|
||||
bool restore_dbg_registers,
|
||||
uint32_t vmid)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, 0);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, 0);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Returns TRAP_EN, EXCP_EN and EXCP_REPLACE. */
|
||||
static uint32_t kgd_gfx_v11_disable_debug_trap(struct amdgpu_device *adev,
|
||||
bool keep_trap_enabled,
|
||||
uint32_t vmid)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, keep_trap_enabled);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, 0);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, 0);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static int kgd_gfx_v11_validate_trap_override_request(struct amdgpu_device *adev,
|
||||
uint32_t trap_override,
|
||||
uint32_t *trap_mask_supported)
|
||||
{
|
||||
*trap_mask_supported &= KFD_DBG_TRAP_MASK_FP_INVALID |
|
||||
KFD_DBG_TRAP_MASK_FP_INPUT_DENORMAL |
|
||||
KFD_DBG_TRAP_MASK_FP_DIVIDE_BY_ZERO |
|
||||
KFD_DBG_TRAP_MASK_FP_OVERFLOW |
|
||||
KFD_DBG_TRAP_MASK_FP_UNDERFLOW |
|
||||
KFD_DBG_TRAP_MASK_FP_INEXACT |
|
||||
KFD_DBG_TRAP_MASK_INT_DIVIDE_BY_ZERO |
|
||||
KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH |
|
||||
KFD_DBG_TRAP_MASK_DBG_MEMORY_VIOLATION;
|
||||
|
||||
if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 4))
|
||||
*trap_mask_supported |= KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_START |
|
||||
KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_END;
|
||||
|
||||
if (trap_override != KFD_DBG_TRAP_OVERRIDE_OR &&
|
||||
trap_override != KFD_DBG_TRAP_OVERRIDE_REPLACE)
|
||||
return -EPERM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t trap_mask_map_sw_to_hw(uint32_t mask)
|
||||
{
|
||||
uint32_t trap_on_start = (mask & KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_START) ? 1 : 0;
|
||||
uint32_t trap_on_end = (mask & KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_END) ? 1 : 0;
|
||||
uint32_t excp_en = mask & (KFD_DBG_TRAP_MASK_FP_INVALID |
|
||||
KFD_DBG_TRAP_MASK_FP_INPUT_DENORMAL |
|
||||
KFD_DBG_TRAP_MASK_FP_DIVIDE_BY_ZERO |
|
||||
KFD_DBG_TRAP_MASK_FP_OVERFLOW |
|
||||
KFD_DBG_TRAP_MASK_FP_UNDERFLOW |
|
||||
KFD_DBG_TRAP_MASK_FP_INEXACT |
|
||||
KFD_DBG_TRAP_MASK_INT_DIVIDE_BY_ZERO |
|
||||
KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH |
|
||||
KFD_DBG_TRAP_MASK_DBG_MEMORY_VIOLATION);
|
||||
uint32_t ret;
|
||||
|
||||
ret = REG_SET_FIELD(0, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, excp_en);
|
||||
ret = REG_SET_FIELD(ret, SPI_GDBG_PER_VMID_CNTL, TRAP_ON_START, trap_on_start);
|
||||
ret = REG_SET_FIELD(ret, SPI_GDBG_PER_VMID_CNTL, TRAP_ON_END, trap_on_end);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t trap_mask_map_hw_to_sw(uint32_t mask)
|
||||
{
|
||||
uint32_t ret = REG_GET_FIELD(mask, SPI_GDBG_PER_VMID_CNTL, EXCP_EN);
|
||||
|
||||
if (REG_GET_FIELD(mask, SPI_GDBG_PER_VMID_CNTL, TRAP_ON_START))
|
||||
ret |= KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_START;
|
||||
|
||||
if (REG_GET_FIELD(mask, SPI_GDBG_PER_VMID_CNTL, TRAP_ON_END))
|
||||
ret |= KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_END;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returns TRAP_EN, EXCP_EN and EXCP_REPLACE. */
|
||||
static uint32_t kgd_gfx_v11_set_wave_launch_trap_override(struct amdgpu_device *adev,
|
||||
uint32_t vmid,
|
||||
uint32_t trap_override,
|
||||
uint32_t trap_mask_bits,
|
||||
uint32_t trap_mask_request,
|
||||
uint32_t *trap_mask_prev,
|
||||
uint32_t kfd_dbg_trap_cntl_prev)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
*trap_mask_prev = trap_mask_map_hw_to_sw(kfd_dbg_trap_cntl_prev);
|
||||
|
||||
data = (trap_mask_bits & trap_mask_request) | (*trap_mask_prev & ~trap_mask_request);
|
||||
data = trap_mask_map_sw_to_hw(data);
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, trap_override);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static uint32_t kgd_gfx_v11_set_wave_launch_mode(struct amdgpu_device *adev,
|
||||
uint8_t wave_launch_mode,
|
||||
uint32_t vmid)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, LAUNCH_MODE, wave_launch_mode);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#define TCP_WATCH_STRIDE (regTCP_WATCH1_ADDR_H - regTCP_WATCH0_ADDR_H)
|
||||
static uint32_t kgd_gfx_v11_set_address_watch(struct amdgpu_device *adev,
|
||||
uint64_t watch_address,
|
||||
uint32_t watch_address_mask,
|
||||
uint32_t watch_id,
|
||||
uint32_t watch_mode,
|
||||
uint32_t debug_vmid)
|
||||
{
|
||||
uint32_t watch_address_high;
|
||||
uint32_t watch_address_low;
|
||||
uint32_t watch_address_cntl;
|
||||
|
||||
watch_address_cntl = 0;
|
||||
watch_address_low = lower_32_bits(watch_address);
|
||||
watch_address_high = upper_32_bits(watch_address) & 0xffff;
|
||||
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
MODE,
|
||||
watch_mode);
|
||||
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
MASK,
|
||||
watch_address_mask >> 7);
|
||||
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
VALID,
|
||||
1);
|
||||
|
||||
WREG32_RLC((SOC15_REG_OFFSET(GC, 0, regTCP_WATCH0_ADDR_H) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_high);
|
||||
|
||||
WREG32_RLC((SOC15_REG_OFFSET(GC, 0, regTCP_WATCH0_ADDR_L) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_low);
|
||||
|
||||
return watch_address_cntl;
|
||||
}
|
||||
|
||||
static uint32_t kgd_gfx_v11_clear_address_watch(struct amdgpu_device *adev,
|
||||
uint32_t watch_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls gfx_v11_kfd2kgd = {
|
||||
.program_sh_mem_settings = program_sh_mem_settings_v11,
|
||||
.set_pasid_vmid_mapping = set_pasid_vmid_mapping_v11,
|
||||
@@ -622,4 +801,11 @@ const struct kfd2kgd_calls gfx_v11_kfd2kgd = {
|
||||
.wave_control_execute = wave_control_execute_v11,
|
||||
.get_atc_vmid_pasid_mapping_info = NULL,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base_v11,
|
||||
.enable_debug_trap = kgd_gfx_v11_enable_debug_trap,
|
||||
.disable_debug_trap = kgd_gfx_v11_disable_debug_trap,
|
||||
.validate_trap_override_request = kgd_gfx_v11_validate_trap_override_request,
|
||||
.set_wave_launch_trap_override = kgd_gfx_v11_set_wave_launch_trap_override,
|
||||
.set_wave_launch_mode = kgd_gfx_v11_set_wave_launch_mode,
|
||||
.set_address_watch = kgd_gfx_v11_set_address_watch,
|
||||
.clear_address_watch = kgd_gfx_v11_clear_address_watch
|
||||
};
|
||||
@@ -78,7 +78,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
uint32_t sh_mem_bases, uint32_t inst)
|
||||
{
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
@@ -91,7 +91,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
unsigned int vmid)
|
||||
unsigned int vmid, uint32_t inst)
|
||||
{
|
||||
/*
|
||||
* We have to assume that there is no outstanding mapping.
|
||||
@@ -114,7 +114,8 @@ static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t inst)
|
||||
{
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
@@ -158,7 +159,7 @@ static inline struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd)
|
||||
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm)
|
||||
uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
|
||||
{
|
||||
struct cik_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
@@ -202,7 +203,7 @@ static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
|
||||
static int kgd_hqd_dump(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
|
||||
{
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS (35+4)
|
||||
@@ -318,7 +319,7 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
|
||||
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
@@ -358,7 +359,7 @@ static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
uint32_t temp;
|
||||
enum hqd_dequeue_request_type type;
|
||||
@@ -494,7 +495,7 @@ static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
|
||||
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
uint32_t sq_cmd, uint32_t inst)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
uint32_t sh_mem_bases, uint32_t inst)
|
||||
{
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
@@ -85,7 +85,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
unsigned int vmid)
|
||||
unsigned int vmid, uint32_t inst)
|
||||
{
|
||||
/*
|
||||
* We have to assume that there is no outstanding mapping.
|
||||
@@ -109,7 +109,8 @@ static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t inst)
|
||||
{
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
@@ -153,7 +154,7 @@ static inline struct vi_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm)
|
||||
uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
|
||||
{
|
||||
struct vi_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
@@ -226,7 +227,7 @@ static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
|
||||
static int kgd_hqd_dump(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
|
||||
{
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS (54+4)
|
||||
@@ -350,7 +351,7 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
|
||||
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
@@ -390,7 +391,7 @@ static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
uint32_t queue_id, uint32_t inst)
|
||||
{
|
||||
uint32_t temp;
|
||||
enum hqd_dequeue_request_type type;
|
||||
@@ -540,7 +541,7 @@ static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
|
||||
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
uint32_t sq_cmd, uint32_t inst)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -20,41 +20,81 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
void kgd_gfx_v9_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base, uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases);
|
||||
uint32_t sh_mem_bases, uint32_t inst);
|
||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
unsigned int vmid);
|
||||
int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id);
|
||||
unsigned int vmid, uint32_t inst);
|
||||
int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t inst);
|
||||
int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm);
|
||||
struct mm_struct *mm, uint32_t inst);
|
||||
int kgd_gfx_v9_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t doorbell_off);
|
||||
uint32_t doorbell_off, uint32_t inst);
|
||||
int kgd_gfx_v9_hqd_dump(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs);
|
||||
uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst);
|
||||
bool kgd_gfx_v9_hqd_is_occupied(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id);
|
||||
uint32_t queue_id, uint32_t inst);
|
||||
int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id);
|
||||
uint32_t queue_id, uint32_t inst);
|
||||
int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd);
|
||||
uint32_t sq_cmd, uint32_t inst);
|
||||
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
uint8_t vmid, uint16_t *p_pasid);
|
||||
|
||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base);
|
||||
void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
|
||||
int *pasid_wave_cnt, int *max_waves_per_cu);
|
||||
int *pasid_wave_cnt, int *max_waves_per_cu, uint32_t inst);
|
||||
void kgd_gfx_v9_program_trap_handler_settings(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr);
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr,
|
||||
uint32_t inst);
|
||||
void kgd_gfx_v9_acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t inst);
|
||||
uint64_t kgd_gfx_v9_get_queue_mask(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id);
|
||||
void kgd_gfx_v9_release_queue(struct amdgpu_device *adev, uint32_t inst);
|
||||
void kgd_gfx_v9_set_wave_launch_stall(struct amdgpu_device *adev,
|
||||
uint32_t vmid,
|
||||
bool stall);
|
||||
uint32_t kgd_gfx_v9_enable_debug_trap(struct amdgpu_device *adev,
|
||||
bool restore_dbg_registers,
|
||||
uint32_t vmid);
|
||||
uint32_t kgd_gfx_v9_disable_debug_trap(struct amdgpu_device *adev,
|
||||
bool keep_trap_enabled,
|
||||
uint32_t vmid);
|
||||
int kgd_gfx_v9_validate_trap_override_request(struct amdgpu_device *adev,
|
||||
uint32_t trap_override,
|
||||
uint32_t *trap_mask_supported);
|
||||
uint32_t kgd_gfx_v9_set_wave_launch_mode(struct amdgpu_device *adev,
|
||||
uint8_t wave_launch_mode,
|
||||
uint32_t vmid);
|
||||
uint32_t kgd_gfx_v9_set_wave_launch_trap_override(struct amdgpu_device *adev,
|
||||
uint32_t vmid,
|
||||
uint32_t trap_override,
|
||||
uint32_t trap_mask_bits,
|
||||
uint32_t trap_mask_request,
|
||||
uint32_t *trap_mask_prev,
|
||||
uint32_t kfd_dbg_trap_cntl_prev);
|
||||
uint32_t kgd_gfx_v9_set_address_watch(struct amdgpu_device *adev,
|
||||
uint64_t watch_address,
|
||||
uint32_t watch_address_mask,
|
||||
uint32_t watch_id,
|
||||
uint32_t watch_mode,
|
||||
uint32_t debug_vmid);
|
||||
uint32_t kgd_gfx_v9_clear_address_watch(struct amdgpu_device *adev,
|
||||
uint32_t watch_id);
|
||||
void kgd_gfx_v9_get_iq_wait_times(struct amdgpu_device *adev, uint32_t *wait_times);
|
||||
void kgd_gfx_v9_build_grace_period_packet_info(struct amdgpu_device *adev,
|
||||
uint32_t wait_times,
|
||||
uint32_t grace_period,
|
||||
uint32_t *reg_offset,
|
||||
uint32_t *reg_data);
|
||||
@@ -35,7 +35,9 @@
|
||||
#include "amdgpu_dma_buf.h"
|
||||
#include <uapi/linux/kfd_ioctl.h>
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include "kfd_priv.h"
|
||||
#include "kfd_smi_events.h"
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
|
||||
/* Userptr restore delay, just long enough to allow consecutive VM
|
||||
* changes to accumulate
|
||||
@@ -110,13 +112,16 @@ void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
|
||||
struct sysinfo si;
|
||||
uint64_t mem;
|
||||
|
||||
if (kfd_mem_limit.max_system_mem_limit)
|
||||
return;
|
||||
|
||||
si_meminfo(&si);
|
||||
mem = si.freeram - si.freehigh;
|
||||
mem *= si.mem_unit;
|
||||
|
||||
spin_lock_init(&kfd_mem_limit.mem_limit_lock);
|
||||
kfd_mem_limit.max_system_mem_limit = mem - (mem >> 4);
|
||||
kfd_mem_limit.max_ttm_mem_limit = (mem >> 1) - (mem >> 3);
|
||||
kfd_mem_limit.max_ttm_mem_limit = ttm_tt_pages_limit() << PAGE_SHIFT;
|
||||
pr_debug("Kernel memory limit %lluM, TTM limit %lluM\n",
|
||||
(kfd_mem_limit.max_system_mem_limit >> 20),
|
||||
(kfd_mem_limit.max_ttm_mem_limit >> 20));
|
||||
@@ -148,16 +153,20 @@ void amdgpu_amdkfd_reserve_system_mem(uint64_t size)
|
||||
* @size: Size of buffer, in bytes, encapsulated by B0. This should be
|
||||
* equivalent to amdgpu_bo_size(BO)
|
||||
* @alloc_flag: Flag used in allocating a BO as noted above
|
||||
* @xcp_id: xcp_id is used to get xcp from xcp manager, one xcp is
|
||||
* managed as one compute node in driver for app
|
||||
*
|
||||
* Return: returns -ENOMEM in case of error, ZERO otherwise
|
||||
* Return:
|
||||
* returns -ENOMEM in case of error, ZERO otherwise
|
||||
*/
|
||||
int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
||||
uint64_t size, u32 alloc_flag)
|
||||
uint64_t size, u32 alloc_flag, int8_t xcp_id)
|
||||
{
|
||||
uint64_t reserved_for_pt =
|
||||
ESTIMATE_PT_SIZE(amdgpu_amdkfd_total_mem_size);
|
||||
size_t system_mem_needed, ttm_mem_needed, vram_needed;
|
||||
int ret = 0;
|
||||
uint64_t vram_size = 0;
|
||||
|
||||
system_mem_needed = 0;
|
||||
ttm_mem_needed = 0;
|
||||
@@ -172,6 +181,17 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
||||
* 2M BO chunk.
|
||||
*/
|
||||
vram_needed = size;
|
||||
/*
|
||||
* For GFX 9.4.3, get the VRAM size from XCP structs
|
||||
*/
|
||||
if (WARN_ONCE(xcp_id < 0, "invalid XCP ID %d", xcp_id))
|
||||
return -EINVAL;
|
||||
|
||||
vram_size = KFD_XCP_MEMORY_SIZE(adev, xcp_id);
|
||||
if (adev->gmc.is_app_apu) {
|
||||
system_mem_needed = size;
|
||||
ttm_mem_needed = size;
|
||||
}
|
||||
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) {
|
||||
system_mem_needed = size;
|
||||
} else if (!(alloc_flag &
|
||||
@@ -191,8 +211,8 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
||||
kfd_mem_limit.max_system_mem_limit && !no_system_mem_limit) ||
|
||||
(kfd_mem_limit.ttm_mem_used + ttm_mem_needed >
|
||||
kfd_mem_limit.max_ttm_mem_limit) ||
|
||||
(adev && adev->kfd.vram_used + vram_needed >
|
||||
adev->gmc.real_vram_size - reserved_for_pt)) {
|
||||
(adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed >
|
||||
vram_size - reserved_for_pt)) {
|
||||
ret = -ENOMEM;
|
||||
goto release;
|
||||
}
|
||||
@@ -202,9 +222,11 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
||||
*/
|
||||
WARN_ONCE(vram_needed && !adev,
|
||||
"adev reference can't be null when vram is used");
|
||||
if (adev) {
|
||||
adev->kfd.vram_used += vram_needed;
|
||||
adev->kfd.vram_used_aligned += ALIGN(vram_needed, VRAM_AVAILABLITY_ALIGN);
|
||||
if (adev && xcp_id >= 0) {
|
||||
adev->kfd.vram_used[xcp_id] += vram_needed;
|
||||
adev->kfd.vram_used_aligned[xcp_id] += adev->gmc.is_app_apu ?
|
||||
vram_needed :
|
||||
ALIGN(vram_needed, VRAM_AVAILABLITY_ALIGN);
|
||||
}
|
||||
kfd_mem_limit.system_mem_used += system_mem_needed;
|
||||
kfd_mem_limit.ttm_mem_used += ttm_mem_needed;
|
||||
@@ -215,7 +237,7 @@ release:
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
|
||||
uint64_t size, u32 alloc_flag)
|
||||
uint64_t size, u32 alloc_flag, int8_t xcp_id)
|
||||
{
|
||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||
|
||||
@@ -225,9 +247,19 @@ void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
|
||||
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
|
||||
WARN_ONCE(!adev,
|
||||
"adev reference can't be null when alloc mem flags vram is set");
|
||||
if (WARN_ONCE(xcp_id < 0, "invalid XCP ID %d", xcp_id))
|
||||
goto release;
|
||||
|
||||
if (adev) {
|
||||
adev->kfd.vram_used -= size;
|
||||
adev->kfd.vram_used_aligned -= ALIGN(size, VRAM_AVAILABLITY_ALIGN);
|
||||
adev->kfd.vram_used[xcp_id] -= size;
|
||||
if (adev->gmc.is_app_apu) {
|
||||
adev->kfd.vram_used_aligned[xcp_id] -= size;
|
||||
kfd_mem_limit.system_mem_used -= size;
|
||||
kfd_mem_limit.ttm_mem_used -= size;
|
||||
} else {
|
||||
adev->kfd.vram_used_aligned[xcp_id] -=
|
||||
ALIGN(size, VRAM_AVAILABLITY_ALIGN);
|
||||
}
|
||||
}
|
||||
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) {
|
||||
kfd_mem_limit.system_mem_used -= size;
|
||||
@@ -237,8 +269,8 @@ void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
|
||||
pr_err("%s: Invalid BO type %#x\n", __func__, alloc_flag);
|
||||
goto release;
|
||||
}
|
||||
WARN_ONCE(adev && adev->kfd.vram_used < 0,
|
||||
"KFD VRAM memory accounting unbalanced");
|
||||
WARN_ONCE(adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] < 0,
|
||||
"KFD VRAM memory accounting unbalanced for xcp: %d", xcp_id);
|
||||
WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0,
|
||||
"KFD TTM memory accounting unbalanced");
|
||||
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
|
||||
@@ -254,14 +286,16 @@ void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo)
|
||||
u32 alloc_flags = bo->kfd_bo->alloc_flags;
|
||||
u64 size = amdgpu_bo_size(bo);
|
||||
|
||||
amdgpu_amdkfd_unreserve_mem_limit(adev, size, alloc_flags);
|
||||
amdgpu_amdkfd_unreserve_mem_limit(adev, size, alloc_flags,
|
||||
bo->xcp_id);
|
||||
|
||||
kfree(bo->kfd_bo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @create_dmamap_sg_bo: Creates a amdgpu_bo object to reflect information
|
||||
* create_dmamap_sg_bo() - Creates a amdgpu_bo object to reflect information
|
||||
* about USERPTR or DOOREBELL or MMIO BO.
|
||||
*
|
||||
* @adev: Device for which dmamap BO is being created
|
||||
* @mem: BO of peer device that is being DMA mapped. Provides parameters
|
||||
* in building the dmamap BO
|
||||
@@ -285,7 +319,7 @@ create_dmamap_sg_bo(struct amdgpu_device *adev,
|
||||
|
||||
ret = amdgpu_gem_object_create(adev, mem->bo->tbo.base.size, 1,
|
||||
AMDGPU_GEM_DOMAIN_CPU, AMDGPU_GEM_CREATE_PREEMPTIBLE | flags,
|
||||
ttm_bo_type_sg, mem->bo->tbo.base.resv, &gem_obj);
|
||||
ttm_bo_type_sg, mem->bo->tbo.base.resv, &gem_obj, 0);
|
||||
|
||||
amdgpu_bo_unreserve(mem->bo);
|
||||
|
||||
@@ -527,6 +561,12 @@ kfd_mem_dmamap_dmabuf(struct kfd_mem_attachment *attachment)
|
||||
{
|
||||
struct ttm_operation_ctx ctx = {.interruptible = true};
|
||||
struct amdgpu_bo *bo = attachment->bo_va->base.bo;
|
||||
int ret;
|
||||
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
|
||||
ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT);
|
||||
return ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
@@ -659,11 +699,10 @@ kfd_mem_dmaunmap_userptr(struct kgd_mem *mem,
|
||||
static void
|
||||
kfd_mem_dmaunmap_dmabuf(struct kfd_mem_attachment *attachment)
|
||||
{
|
||||
struct ttm_operation_ctx ctx = {.interruptible = true};
|
||||
struct amdgpu_bo *bo = attachment->bo_va->base.bo;
|
||||
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
|
||||
ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
/* This is a no-op. We don't want to trigger eviction fences when
|
||||
* unmapping DMABufs. Therefore the invalidation (moving to system
|
||||
* domain) is done in kfd_mem_dmamap_dmabuf.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -804,7 +843,7 @@ static int kfd_mem_attach(struct amdgpu_device *adev, struct kgd_mem *mem,
|
||||
* if peer device has large BAR. In contrast, access over xGMI is
|
||||
* allowed for both small and large BAR configurations of peer device
|
||||
*/
|
||||
if ((adev != bo_adev) &&
|
||||
if ((adev != bo_adev && !adev->gmc.is_app_apu) &&
|
||||
((mem->domain == AMDGPU_GEM_DOMAIN_VRAM) ||
|
||||
(mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) ||
|
||||
(mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP))) {
|
||||
@@ -1599,23 +1638,42 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev)
|
||||
size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev,
|
||||
uint8_t xcp_id)
|
||||
{
|
||||
uint64_t reserved_for_pt =
|
||||
ESTIMATE_PT_SIZE(amdgpu_amdkfd_total_mem_size);
|
||||
ssize_t available;
|
||||
uint64_t vram_available, system_mem_available, ttm_mem_available;
|
||||
|
||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||
available = adev->gmc.real_vram_size
|
||||
- adev->kfd.vram_used_aligned
|
||||
vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id)
|
||||
- adev->kfd.vram_used_aligned[xcp_id]
|
||||
- atomic64_read(&adev->vram_pin_size)
|
||||
- reserved_for_pt;
|
||||
|
||||
if (adev->gmc.is_app_apu) {
|
||||
system_mem_available = no_system_mem_limit ?
|
||||
kfd_mem_limit.max_system_mem_limit :
|
||||
kfd_mem_limit.max_system_mem_limit -
|
||||
kfd_mem_limit.system_mem_used;
|
||||
|
||||
ttm_mem_available = kfd_mem_limit.max_ttm_mem_limit -
|
||||
kfd_mem_limit.ttm_mem_used;
|
||||
|
||||
available = min3(system_mem_available, ttm_mem_available,
|
||||
vram_available);
|
||||
available = ALIGN_DOWN(available, PAGE_SIZE);
|
||||
} else {
|
||||
available = ALIGN_DOWN(vram_available, VRAM_AVAILABLITY_ALIGN);
|
||||
}
|
||||
|
||||
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
||||
|
||||
if (available < 0)
|
||||
available = 0;
|
||||
|
||||
return ALIGN_DOWN(available, VRAM_AVAILABLITY_ALIGN);
|
||||
return available;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
@@ -1624,6 +1682,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
uint64_t *offset, uint32_t flags, bool criu_resume)
|
||||
{
|
||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||
struct amdgpu_fpriv *fpriv = container_of(avm, struct amdgpu_fpriv, vm);
|
||||
enum ttm_bo_type bo_type = ttm_bo_type_device;
|
||||
struct sg_table *sg = NULL;
|
||||
uint64_t user_addr = 0;
|
||||
@@ -1631,6 +1690,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
u32 domain, alloc_domain;
|
||||
uint64_t aligned_size;
|
||||
int8_t xcp_id = -1;
|
||||
u64 alloc_flags;
|
||||
int ret;
|
||||
|
||||
@@ -1639,9 +1699,17 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
*/
|
||||
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
|
||||
domain = alloc_domain = AMDGPU_GEM_DOMAIN_VRAM;
|
||||
alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
|
||||
alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ?
|
||||
|
||||
if (adev->gmc.is_app_apu) {
|
||||
domain = AMDGPU_GEM_DOMAIN_GTT;
|
||||
alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
|
||||
alloc_flags = 0;
|
||||
} else {
|
||||
alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
|
||||
alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ?
|
||||
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED : 0;
|
||||
}
|
||||
xcp_id = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id;
|
||||
} else if (flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) {
|
||||
domain = alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
|
||||
alloc_flags = 0;
|
||||
@@ -1693,17 +1761,19 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
|
||||
amdgpu_sync_create(&(*mem)->sync);
|
||||
|
||||
ret = amdgpu_amdkfd_reserve_mem_limit(adev, aligned_size, flags);
|
||||
ret = amdgpu_amdkfd_reserve_mem_limit(adev, aligned_size, flags,
|
||||
xcp_id);
|
||||
if (ret) {
|
||||
pr_debug("Insufficient memory\n");
|
||||
goto err_reserve_limit;
|
||||
}
|
||||
|
||||
pr_debug("\tcreate BO VA 0x%llx size 0x%llx domain %s\n",
|
||||
va, (*mem)->aql_queue ? size << 1 : size, domain_string(alloc_domain));
|
||||
pr_debug("\tcreate BO VA 0x%llx size 0x%llx domain %s xcp_id %d\n",
|
||||
va, (*mem)->aql_queue ? size << 1 : size,
|
||||
domain_string(alloc_domain), xcp_id);
|
||||
|
||||
ret = amdgpu_gem_object_create(adev, aligned_size, 1, alloc_domain, alloc_flags,
|
||||
bo_type, NULL, &gobj);
|
||||
bo_type, NULL, &gobj, xcp_id + 1);
|
||||
if (ret) {
|
||||
pr_debug("Failed to create BO on domain %s. ret %d\n",
|
||||
domain_string(alloc_domain), ret);
|
||||
@@ -1728,6 +1798,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
(*mem)->domain = domain;
|
||||
(*mem)->mapped_to_gpu_memory = 0;
|
||||
(*mem)->process_info = avm->process_info;
|
||||
|
||||
add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
|
||||
|
||||
if (user_addr) {
|
||||
@@ -1759,7 +1830,7 @@ err_node_allow:
|
||||
/* Don't unreserve system mem limit twice */
|
||||
goto err_reserve_limit;
|
||||
err_bo_create:
|
||||
amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags);
|
||||
amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags, xcp_id);
|
||||
err_reserve_limit:
|
||||
mutex_destroy(&(*mem)->lock);
|
||||
if (gobj)
|
||||
@@ -1855,11 +1926,14 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
}
|
||||
|
||||
/* Update the size of the BO being freed if it was allocated from
|
||||
* VRAM and is not imported.
|
||||
* VRAM and is not imported. For APP APU VRAM allocations are done
|
||||
* in GTT domain
|
||||
*/
|
||||
if (size) {
|
||||
if ((mem->bo->preferred_domains == AMDGPU_GEM_DOMAIN_VRAM) &&
|
||||
(!is_imported))
|
||||
if (!is_imported &&
|
||||
(mem->bo->preferred_domains == AMDGPU_GEM_DOMAIN_VRAM ||
|
||||
(adev->gmc.is_app_apu &&
|
||||
mem->bo->preferred_domains == AMDGPU_GEM_DOMAIN_GTT)))
|
||||
*size = bo_size;
|
||||
else
|
||||
*size = 0;
|
||||
@@ -2282,8 +2356,9 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
|
||||
(*mem)->dmabuf = dma_buf;
|
||||
(*mem)->bo = bo;
|
||||
(*mem)->va = va;
|
||||
(*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
|
||||
(*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) && !adev->gmc.is_app_apu ?
|
||||
AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT;
|
||||
|
||||
(*mem)->mapped_to_gpu_memory = 0;
|
||||
(*mem)->process_info = avm->process_info;
|
||||
add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, false);
|
||||
@@ -2445,7 +2520,9 @@ static int update_invalid_user_pages(struct amdkfd_process_info *process_info,
|
||||
ret = -EAGAIN;
|
||||
goto unlock_out;
|
||||
}
|
||||
mem->invalid = 0;
|
||||
/* set mem valid if mem has hmm range associated */
|
||||
if (mem->range)
|
||||
mem->invalid = 0;
|
||||
}
|
||||
|
||||
unlock_out:
|
||||
@@ -2577,8 +2654,15 @@ static int confirm_valid_user_pages_locked(struct amdkfd_process_info *process_i
|
||||
list_for_each_entry_safe(mem, tmp_mem,
|
||||
&process_info->userptr_inval_list,
|
||||
validate_list.head) {
|
||||
bool valid = amdgpu_ttm_tt_get_user_pages_done(
|
||||
mem->bo->tbo.ttm, mem->range);
|
||||
bool valid;
|
||||
|
||||
/* keep mem without hmm range at userptr_inval_list */
|
||||
if (!mem->range)
|
||||
continue;
|
||||
|
||||
/* Only check mem with hmm range associated */
|
||||
valid = amdgpu_ttm_tt_get_user_pages_done(
|
||||
mem->bo->tbo.ttm, mem->range);
|
||||
|
||||
mem->range = NULL;
|
||||
if (!valid) {
|
||||
@@ -2586,7 +2670,12 @@ static int confirm_valid_user_pages_locked(struct amdkfd_process_info *process_i
|
||||
ret = -EAGAIN;
|
||||
continue;
|
||||
}
|
||||
WARN(mem->invalid, "Valid BO is marked invalid");
|
||||
|
||||
if (mem->invalid) {
|
||||
WARN(1, "Valid BO is marked invalid");
|
||||
ret = -EAGAIN;
|
||||
continue;
|
||||
}
|
||||
|
||||
list_move_tail(&mem->validate_list.head,
|
||||
&process_info->userptr_valid_list);
|
||||
|
||||
Loaded 20 of 498 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user